Initial Commit
This commit is contained in:
173
database/perl/vendor/lib/IPC/Run/Win32Pump.pm
vendored
Normal file
173
database/perl/vendor/lib/IPC/Run/Win32Pump.pm
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
package IPC::Run::Win32Pump;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
IPC::Run::Win32Pump - helper processes to shovel data to/from parent, child
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Internal use only; see IPC::Run::Win32IO and best of luck to you.
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
See L<IPC::Run::Win32Helper|IPC::Run::Win32Helper> for details. This
|
||||
module is used in subprocesses that are spawned to shovel data to/from
|
||||
parent processes from/to their child processes. Where possible, pumps
|
||||
are optimized away.
|
||||
|
||||
NOTE: This is not a real module: it's a script in module form, designed
|
||||
to be run like
|
||||
|
||||
$^X -MIPC::Run::Win32Pumper -e 1 ...
|
||||
|
||||
It parses a bunch of command line parameters from IPC::Run::Win32IO.
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use vars qw{$VERSION};
|
||||
|
||||
BEGIN {
|
||||
$VERSION = '20200505.0';
|
||||
}
|
||||
|
||||
use Win32API::File qw(
|
||||
OsFHandleOpen
|
||||
);
|
||||
|
||||
my ( $stdin_fh, $stdout_fh, $debug_fh, $binmode, $parent_pid, $parent_start_time, $debug, $child_label );
|
||||
|
||||
BEGIN {
|
||||
( $stdin_fh, $stdout_fh, $debug_fh, $binmode, $parent_pid, $parent_start_time, $debug, $child_label ) = @ARGV;
|
||||
## Rather than letting IPC::Run::Debug export all-0 constants
|
||||
## when not debugging, we do it manually in order to not even
|
||||
## load IPC::Run::Debug.
|
||||
if ($debug) {
|
||||
eval "use IPC::Run::Debug qw( :default _debug_init ); 1;"
|
||||
or die $@;
|
||||
}
|
||||
else {
|
||||
eval <<STUBS_END or die $@;
|
||||
sub _debug {}
|
||||
sub _debug_init {}
|
||||
sub _debugging() { 0 }
|
||||
sub _debugging_data() { 0 }
|
||||
sub _debugging_details() { 0 }
|
||||
sub _debugging_gory_details() { 0 }
|
||||
1;
|
||||
STUBS_END
|
||||
}
|
||||
}
|
||||
|
||||
## For some reason these get created with binmode on. AAargh, gotta #### REMOVE
|
||||
## do it by hand below. #### REMOVE
|
||||
if ($debug) { #### REMOVE
|
||||
close STDERR; #### REMOVE
|
||||
OsFHandleOpen( \*STDERR, $debug_fh, "w" ) #### REMOVE
|
||||
or print "$! opening STDERR as Win32 handle $debug_fh in pumper $$"; #### REMOVE
|
||||
} #### REMOVE
|
||||
close STDIN; #### REMOVE
|
||||
OsFHandleOpen( \*STDIN, $stdin_fh, "r" ) #### REMOVE
|
||||
or die "$! opening STDIN as Win32 handle $stdin_fh in pumper $$"; #### REMOVE
|
||||
close STDOUT; #### REMOVE
|
||||
OsFHandleOpen( \*STDOUT, $stdout_fh, "w" ) #### REMOVE
|
||||
or die "$! opening STDOUT as Win32 handle $stdout_fh in pumper $$"; #### REMOVE
|
||||
|
||||
binmode STDIN;
|
||||
binmode STDOUT;
|
||||
$| = 1;
|
||||
select STDERR;
|
||||
$| = 1;
|
||||
select STDOUT;
|
||||
|
||||
$child_label ||= "pump";
|
||||
_debug_init(
|
||||
$parent_pid,
|
||||
$parent_start_time,
|
||||
$debug,
|
||||
fileno STDERR,
|
||||
$child_label,
|
||||
);
|
||||
|
||||
_debug "Entered" if _debugging_details;
|
||||
|
||||
# No need to close all fds; win32 doesn't seem to pass any on to us.
|
||||
$| = 1;
|
||||
my $buf;
|
||||
my $total_count = 0;
|
||||
while (1) {
|
||||
my $count = sysread STDIN, $buf, 10_000;
|
||||
last unless $count;
|
||||
if (_debugging_gory_details) {
|
||||
my $msg = "'$buf'";
|
||||
substr( $msg, 100, -1 ) = '...' if length $msg > 100;
|
||||
$msg =~ s/\n/\\n/g;
|
||||
$msg =~ s/\r/\\r/g;
|
||||
$msg =~ s/\t/\\t/g;
|
||||
$msg =~ s/([\000-\037\177-\277])/sprintf "\0x%02x", ord $1/eg;
|
||||
_debug sprintf( "%5d chars revc: ", $count ), $msg;
|
||||
}
|
||||
$total_count += $count;
|
||||
$buf =~ s/\r//g unless $binmode;
|
||||
if (_debugging_gory_details) {
|
||||
my $msg = "'$buf'";
|
||||
substr( $msg, 100, -1 ) = '...' if length $msg > 100;
|
||||
$msg =~ s/\n/\\n/g;
|
||||
$msg =~ s/\r/\\r/g;
|
||||
$msg =~ s/\t/\\t/g;
|
||||
$msg =~ s/([\000-\037\177-\277])/sprintf "\0x%02x", ord $1/eg;
|
||||
_debug sprintf( "%5d chars sent: ", $count ), $msg;
|
||||
}
|
||||
print $buf;
|
||||
}
|
||||
|
||||
_debug "Exiting, transferred $total_count chars" if _debugging_details;
|
||||
|
||||
## Perform a graceful socket shutdown. Windows defaults to SO_DONTLINGER,
|
||||
## which should cause a "graceful shutdown in the background" on sockets.
|
||||
## but that's only true if the process closes the socket manually, it
|
||||
## seems; if the process exits and lets the OS clean up, the OS is not
|
||||
## so kind. STDOUT is not always a socket, of course, but it won't hurt
|
||||
## to close a pipe and may even help. With a closed source OS, who
|
||||
## can tell?
|
||||
##
|
||||
## In any case, this close() is one of the main reasons we have helper
|
||||
## processes; if the OS closed socket fds gracefully when an app exits,
|
||||
## we'd just redirect the client directly to what is now the pump end
|
||||
## of the socket. As it is, however, we need to let the client play with
|
||||
## pipes, which don't have the abort-on-app-exit behavior, and then
|
||||
## adapt to the sockets in the helper processes to allow the parent to
|
||||
## select.
|
||||
##
|
||||
## Possible alternatives / improvements:
|
||||
##
|
||||
## 1) use helper threads instead of processes. I don't trust perl's threads
|
||||
## as of 5.005 or 5.6 enough (which may be myopic of me).
|
||||
##
|
||||
## 2) figure out if/how to get at WaitForMultipleObjects() with pipe
|
||||
## handles. May be able to take the Win32 handle and pass it to
|
||||
## Win32::Event::wait_any, dunno.
|
||||
##
|
||||
## 3) Use Inline::C or a hand-tooled XS module to do helper threads.
|
||||
## This would be faster than #1, but would require a ppm distro.
|
||||
##
|
||||
close STDOUT;
|
||||
close STDERR;
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Barries Slaymaker <barries@slaysys.com>. Funded by Perforce Software, Inc.
|
||||
|
||||
=head1 COPYRIGHT
|
||||
|
||||
Copyright 2001, Barrie Slaymaker, All Rights Reserved.
|
||||
|
||||
You may use this under the terms of either the GPL 2.0 ir the Artistic License.
|
||||
|
||||
=cut
|
||||
Reference in New Issue
Block a user