File Coverage

blib/lib/POE/Wheel/Run.pm
Criterion Covered Total %
statement 376 561 67.0
branch 215 382 56.2
condition 78 157 49.6
subroutine 30 45 66.6
pod 20 21 95.2
total 719 1166 61.6


line stmt bran cond sub pod time code
1             package POE::Wheel::Run;
2              
3 73     73   19817 use strict;
  73         105  
  73         2761  
4              
5 73     73   278 use vars qw($VERSION @ISA);
  73         112  
  73         3696  
6             $VERSION = '1.370'; # NOTE - Should be #.### (three decimal places)
7              
8 73     73   253 use Carp qw(carp croak);
  73         86  
  73         4523  
9 73         612 use POSIX qw(
10             sysconf setsid _SC_OPEN_MAX ECHO ICANON IEXTEN ISIG BRKINT ICRNL
11             INPCK ISTRIP IXON CSIZE PARENB OPOST TCSANOW
12 73     73   282 );
  73         200  
13              
14 73     73   9879 use POE qw( Wheel Pipe::TwoWay Pipe::OneWay Driver::SysRW Filter::Line );
  73         113  
  73         771  
15             push @ISA, qw(POE::Wheel);
16              
17             # http://rt.cpan.org/Ticket/Display.html?id=50068
18             # Avoid using these constants in Windows' subprocesses (actually
19             # interpreter threads). Reported in the above ticket to avoid a
20             # memory leak.
21             my ($STD_INPUT_HANDLE, $STD_OUTPUT_HANDLE, $STD_ERROR_HANDLE);
22              
23             BEGIN {
24 73 50   73   551 die "$^O does not support fork()\n" if $^O eq 'MacOS';
25              
26 73         650 local $SIG{'__DIE__'} = 'DEFAULT';
27 73         194 eval { require IO::Pty; };
  73         31756  
28 73 50       342228 if ($@) {
29 0         0 eval '
30             sub PTY_AVAILABLE () { 0 }
31             sub TIOCSWINSZ_AVAILABLE () { 0 }
32             ';
33             }
34             else {
35 73         1763 IO::Pty->import();
36 73         2810 eval 'sub PTY_AVAILABLE () { 1 }';
37              
38 73         190 eval { require IO::Tty; };
  73         414  
39 73 50       232 if ($@) {
40 0         0 eval 'sub TIOCSWINSZ_AVAILABLE () { 0 }';
41             }
42             else {
43 73         263 IO::Tty->import('TIOCSWINSZ');
44 73         6585 eval 'sub TIOCSWINSZ_AVAILABLE () { 1 }';
45             }
46             }
47              
48 73 50       370 if (POE::Kernel::RUNNING_IN_HELL) {
49 0         0 eval { require Win32::Console; Win32::Console->import() };
  0         0  
  0         0  
50 0 0       0 if ($@) { die "Win32::Console needed for POE::Wheel::Run on $^O:\n$@" }
  0         0  
51              
52 0         0 eval {
53 0         0 require Win32API::File;
54 0         0 Win32API::File->import("FdGetOsFHandle");
55             };
56 0 0       0 if ($@) { die "Win32API::File needed for POE::Wheel::Run on $^O:\n$@" }
  0         0  
57              
58 0         0 eval { require Win32::Process; Win32::Process->import() };
  0         0  
  0         0  
59 0 0       0 if ($@) { die "Win32::Process needed for POE::Wheel::Run on $^O:\n$@" }
  0         0  
60              
61 0         0 eval { require Win32::Job; Win32::Job->import() };
  0         0  
  0         0  
62 0 0       0 if ($@) { die "Win32::Job needed for POE::Wheel::Run on $^O:\n$@" }
  0         0  
63              
64 0         0 eval { require Win32; Win32->import() };
  0         0  
  0         0  
65 0 0       0 if ($@) { die "Win32.pm needed for POE::Wheel::Run on $^O:\n$@" }
  0         0  
66              
67 0         0 $STD_INPUT_HANDLE = STD_INPUT_HANDLE();
68 0         0 $STD_OUTPUT_HANDLE = STD_OUTPUT_HANDLE();
69 0         0 $STD_ERROR_HANDLE = STD_ERROR_HANDLE();
70             }
71              
72             # Determine the most file descriptors we can use.
73 73         120 my $max_open_fds;
74 73         111 eval {
75 73         795 $max_open_fds = sysconf(_SC_OPEN_MAX);
76             };
77 73 50       198 $max_open_fds = 1024 unless $max_open_fds;
78 73         1881 eval "sub MAX_OPEN_FDS () { $max_open_fds }";
79 73 50       412845 die if $@;
80             };
81              
82             # Offsets into $self.
83             sub UNIQUE_ID () { 0 }
84             sub ERROR_EVENT () { 1 }
85             sub CLOSE_EVENT () { 2 }
86             sub PROGRAM () { 3 }
87             sub CHILD_PID () { 4 }
88             sub CONDUIT_TYPE () { 5 }
89             sub IS_ACTIVE () { 6 }
90             sub CLOSE_ON_CALL () { 7 }
91             sub STDIO_TYPE () { 8 }
92              
93             sub HANDLE_STDIN () { 9 }
94             sub FILTER_STDIN () { 10 }
95             sub DRIVER_STDIN () { 11 }
96             sub EVENT_STDIN () { 12 }
97             sub STATE_STDIN () { 13 }
98             sub OCTETS_STDIN () { 14 }
99              
100             sub HANDLE_STDOUT () { 15 }
101             sub FILTER_STDOUT () { 16 }
102             sub DRIVER_STDOUT () { 17 }
103             sub EVENT_STDOUT () { 18 }
104             sub STATE_STDOUT () { 19 }
105              
106             sub HANDLE_STDERR () { 20 }
107             sub FILTER_STDERR () { 21 }
108             sub DRIVER_STDERR () { 22 }
109             sub EVENT_STDERR () { 23 }
110             sub STATE_STDERR () { 24 }
111              
112             sub MSWIN32_GROUP_PID () { 25 }
113              
114             # Used to work around a bug in older perl versions.
115 0     0 0 0 sub CRIMSON_SCOPE_HACK ($) { 0 }
116              
117             #------------------------------------------------------------------------------
118              
119             sub new {
120 379     379 1 8082 my $type = shift;
121 379 50       1059 croak "$type needs an even number of parameters" if @_ & 1;
122 379         4813 my %params = @_;
123              
124 379 50 33     2566 croak "wheels no longer require a kernel reference as their first parameter"
125             if @_ and ref($_[0]) eq 'POE::Kernel';
126              
127 379 50       887 croak "$type requires a working Kernel" unless defined $poe_kernel;
128              
129 379         1024 my $program = delete $params{Program};
130 379 100       3298 croak "$type needs a Program parameter" unless defined $program;
131              
132 363         667 my $prog_args = delete $params{ProgramArgs};
133 363 100       807 $prog_args = [] unless defined $prog_args;
134 363 50       1202 croak "ProgramArgs must be an ARRAY reference"
135             unless ref($prog_args) eq "ARRAY";
136              
137 363         816 my $priority_delta = delete $params{Priority};
138 363 50       966 $priority_delta = 0 unless defined $priority_delta;
139              
140 363         664 my $close_on_call = delete $params{CloseOnCall};
141 363 50       817 $close_on_call = 0 unless defined $close_on_call;
142              
143 363         579 my $user_id = delete $params{User};
144 363         1012 my $group_id = delete $params{Group};
145              
146             # The following $stdio_type is new. $conduit is kept around for now
147             # to preserve the logic of the rest of the module. This change
148             # allows a Session using POE::Wheel::Run to define the type of pipe
149             # to be created for stdin and stdout. Read the POD on Conduit.
150             # However, the documentation lies, because if Conduit is undefined,
151             # $stdio_type is set to undefined (so the default pipe type provided
152             # by POE::Pipe::TwoWay will be used). Otherwise, $stdio_type
153             # determines what type of pipe Pipe:TwoWay creates unless it's
154             # 'pty'.
155              
156 363         607 my $conduit = delete $params{Conduit};
157 363         482 my $stdio_type;
158 363 100       702 if (defined $conduit) {
159 72 100 100     3229 croak "$type\'s Conduit type ($conduit) is unknown" if (
      100        
      100        
      100        
160             $conduit ne 'pipe' and
161             $conduit ne 'pty' and
162             $conduit ne 'pty-pipe' and
163             $conduit ne 'socketpair' and
164             $conduit ne 'inet'
165             );
166 56 100       928 unless ($conduit =~ /^pty(-pipe)?$/) {
167 30         98 $stdio_type = $conduit;
168 30         199 $conduit = "pipe";
169             }
170             }
171             else {
172 291         722 $conduit = "pipe";
173             }
174              
175 347         754 my $winsize = delete $params{Winsize};
176              
177 347 50       945 if ($winsize) {
178 0 0 0     0 carp "winsize can only be specified for a Conduit of type pty"
179             if $conduit !~ /^pty(-pipe)?$/ and $winsize;
180              
181 0 0 0     0 if( 'ARRAY' eq ref $winsize and 2==@$winsize ) {
182             # Standard VGA cell in 9x16
183             # http://en.wikipedia.org/wiki/VGA-compatible_text_mode#Fonts
184 0         0 $winsize->[2] = $winsize->[1]*9;
185 0         0 $winsize->[3] = $winsize->[0]*16;
186             }
187 0 0 0     0 carp "winsize must be a 4 element arrayref" unless ref($winsize) eq 'ARRAY'
188             and scalar @$winsize == 4;
189              
190 0         0 carp "winsize only works when IO::Tty::TIOCSWINSZ is"
191             unless TIOCSWINSZ_AVAILABLE;
192             }
193              
194 347         565 my $stdin_event = delete $params{StdinEvent};
195 347         619 my $stdout_event = delete $params{StdoutEvent};
196 347         619 my $stderr_event = delete $params{StderrEvent};
197              
198 347 50 66     1260 if ($conduit eq 'pty' and defined $stderr_event) {
199 0         0 carp "ignoring StderrEvent with pty conduit";
200 0         0 undef $stderr_event;
201             }
202              
203             #croak "$type needs at least one of StdinEvent, StdoutEvent or StderrEvent"
204             # unless (defined($stdin_event) or defined($stdout_event) or defined ($stderr_event));
205              
206 347   33     6939 my $stdio_driver = delete $params{StdioDriver} || POE::Driver::SysRW->new();
207 347   33     1240 my $stdin_driver = delete $params{StdinDriver} || $stdio_driver;
208 347   33     1566 my $stdout_driver = delete $params{StdoutDriver} || $stdio_driver;
209 347   33     1422 my $stderr_driver = delete $params{StderrDriver} || POE::Driver::SysRW->new();
210              
211 347         554 my $stdio_filter = delete $params{Filter};
212 347         515 my $stdin_filter = delete $params{StdinFilter};
213 347         492 my $stdout_filter = delete $params{StdoutFilter};
214 347         560 my $stderr_filter = delete $params{StderrFilter};
215              
216             #For optional redirection...
217 347         442 my $redir_err = delete $params{RedirectStderr};
218 347         538 my $redir_out = delete $params{RedirectStdout};
219 347         509 my $redir_in = delete $params{RedirectStdin};
220 347         544 my $redir_output = delete $params{RedirectOutput};
221              
222 347         497 my $no_stdin = delete $params{NoStdin};
223              
224 347 100       995 if(defined $redir_output) {
225 4         46 $redir_out = $redir_err = $redir_output;
226             }
227              
228             #Sanity check. We can't wait for redirected filehandles
229 347 100 66     4690 if( (defined $redir_in and defined $stdin_event) ||
      100        
      66        
      66        
      66        
230             (defined $redir_out and defined $stdout_event) ||
231             (defined $redir_err and defined $stderr_event) ) {
232 16         1976 croak("Redirect* and *Event stdio options are mutually exclusive");
233             }
234              
235 331 100       729 if (defined $stdio_filter) {
236             croak "Filter and StdioFilter cannot be used together"
237 16 50       2312 if defined $params{StdioFilter};
238 0 0 0     0 croak "Replace deprecated Filter with StdioFilter and StderrFilter"
239             if defined $stderr_event and not defined $stderr_filter;
240 0         0 carp "Filter is deprecated. Please try StdioFilter and/or StderrFilter";
241             }
242             else {
243 315         552 $stdio_filter = delete $params{StdioFilter};
244             }
245 315 100       2875 $stdio_filter = POE::Filter::Line->new(Literal => "\n")
246             unless defined $stdio_filter;
247              
248 315 100       779 $stdin_filter = $stdio_filter unless defined $stdin_filter;
249 315 100       808 $stdout_filter = $stdio_filter unless defined $stdout_filter;
250              
251 315 50 66     1322 if ($conduit eq 'pty' and defined $stderr_filter) {
252 0         0 carp "ignoring StderrFilter with pty conduit";
253 0         0 undef $stderr_filter;
254             }
255             else {
256 315 100       1116 $stderr_filter = POE::Filter::Line->new(Literal => "\n")
257             unless defined $stderr_filter;
258             }
259              
260 315 50 66     2348 croak "$type needs either StdioFilter or StdinFilter when using StdinEvent"
261             if defined($stdin_event) and not defined($stdin_filter);
262 315 50 66     1865 croak "$type needs either StdioFilter or StdoutFilter when using StdoutEvent"
263             if defined($stdout_event) and not defined($stdout_filter);
264 315 50 66     3051 croak "$type needs a StderrFilter when using StderrEvent"
265             if defined($stderr_event) and not defined($stderr_filter);
266              
267 315         547 my $error_event = delete $params{ErrorEvent};
268 315         456 my $close_event = delete $params{CloseEvent};
269              
270 315         458 my $no_setsid = delete $params{NoSetSid};
271 315         439 my $no_setpgrp = delete $params{NoSetPgrp};
272              
273             # Make sure the user didn't pass in parameters we're not aware of.
274 315 50       829 if (scalar keys %params) {
275 0         0 carp(
276             "unknown parameters in $type constructor call: ",
277             join(', ', sort keys %params)
278             );
279             }
280              
281             # Did the user mangle stdio?
282 315 100       994 unless (ref($program) eq 'CODE') {
283 261 50 33     1870 croak "Someone has closed or moved STDIN... exec() won't find it"
284             unless defined fileno(STDIN) && fileno(STDIN) == 0;
285 261 50 33     2401 croak "Someone has closed or moved STDOUT... exec() won't find it"
      33        
286             unless tied(*STDOUT) || defined fileno(STDOUT) && fileno(STDOUT) == 1;
287 261 50 33     1526 croak "Someone has closed or moved STDERR... exec() won't find it"
      66        
288             unless tied(*STDERR) || defined fileno(STDERR) && fileno(STDERR) == 2;
289             }
290              
291             my (
292 315         532 $stdin_read, $stdout_write, $stdout_read, $stdin_write,
293             $stderr_read, $stderr_write,
294             );
295              
296 315         1661 _filespec_to_fh(\$stdin_read, "<", $redir_in);
297 315 100       889 if($redir_output) {
298 4         64 _filespec_to_fh(\$stdout_write, ">", $redir_output);
299 4         132 _filespec_to_fh(\$stderr_write, ">", $stdout_write);
300             } else {
301 311         918 _filespec_to_fh(\$stdout_write, ">", $redir_out);
302 311         610 _filespec_to_fh(\$stderr_write, ">", $redir_err);
303             }
304              
305             # Create a semaphore pipe. This is used so that the parent doesn't
306             # begin listening until the child's stdio has been set up.
307              
308 315         12995 my ($sem_pipe_read, $sem_pipe_write) = POE::Pipe::OneWay->new();
309 315 50       44749 croak "could not create semaphore pipe: $!" unless defined $sem_pipe_read;
310              
311             # Use IO::Pty if requested. IO::Pty turns on autoflush for us.
312              
313 315 100 66     3116 if(defined $stdout_event
      100        
      100        
314             or defined $stdin_event
315             or defined $stderr_event
316             or (!$no_stdin))
317             #Bypass all the conduit handling if the user does not care for child I/O
318             {
319 313 100       10720 if ($conduit =~ /^pty(-pipe)?$/) {
    50          
320 26         103 croak "IO::Pty is not available" unless PTY_AVAILABLE;
321              
322 26 50 33     922 if(defined $redir_err or defined $redir_in or defined $redir_out) {
      33        
323 0         0 croak "Redirection with pty conduit is unsupported";
324             }
325              
326 26         1124 $stdin_write = $stdout_read = IO::Pty->new();
327 26 50       23556 croak "could not create master pty: $!" unless defined $stdout_read;
328 26 100       434 if ($conduit eq "pty-pipe") {
329 12         150 ($stderr_read, $stderr_write) = POE::Pipe::OneWay->new();
330 12 50 33     3620 croak "could not make stderr pipes: $!"
331             unless defined $stderr_read and defined $stderr_write;
332             }
333             }
334              
335             # Use pipes otherwise.
336             elsif ($conduit eq 'pipe') {
337             # We make more pipes than strictly necessary in case someone wants
338             # to turn some on later. Uses a TwoWay pipe for STDIN/STDOUT and
339             # a OneWay pipe for STDERR. This may save 2 filehandles if
340             # socketpair() is available and no other $stdio_type is selected.
341              
342 287         2586 foreach (
343             [\$redir_out, \$stdout_read, \$stdout_write, $stdout_event, "stdout"],
344             [\$redir_err, \$stderr_read, \$stderr_write, $stderr_event, "stderr"],
345             [\$redir_in, \$stdin_read, \$stdin_write, $stdin_event, "stdin"]
346             ) {
347 861         1678 my ($redir_ref,$rfd_ref,$wfd_ref,$evname, $prettyprint) = @$_;
348 861 100 66     3750 if(defined $evname && (!defined $$redir_ref)) {
349 631         2450 ($$rfd_ref,$$wfd_ref) = POE::Pipe::OneWay->new();
350 631 50 33     40668 croak "could not make $prettyprint pipe: $!"
351             unless defined $$rfd_ref and defined $$wfd_ref;
352             }
353             }
354 287 100 66     3137 unless (defined($redir_in) or $no_stdin) {
355 283         1163 ($stdin_read, $stdin_write) = POE::Pipe::OneWay->new();
356 283 50 33     36654 croak "could not make stdin pipe $!"
357             unless defined $stdin_write and defined $stdin_read;
358             }
359             }
360              
361             # Sanity check.
362             else {
363 0         0 croak "unknown conduit type $conduit";
364             }
365             }
366              
367             # Block signals until safe
368 315         577 my $must_unmask;
369 315 50       2078 if( $poe_kernel->can( '_data_sig_mask_all' ) ) {
370 315         1570 $poe_kernel->_data_sig_mask_all;
371 315         516 $must_unmask = 1;
372             }
373              
374             # Fork! Woo-hoo!
375 315         844713 my $pid = fork;
376              
377             # Child. Parent side continues after this block.
378 315 100       14554 unless ($pid) {
379             # removed the croak because it wasn't "safe" RT#56417
380             #croak "couldn't fork: $!" unless defined $pid;
381             # ANY OTHER DIE/CROAK/EXIT/WHATEVER in the child MUST use the helper!
382 49 50       5833 __PACKAGE__->_warn_and_exit_child( "couldn't fork: $!", int( $! ) )
383             unless defined $pid;
384              
385             # Stdio should not be tied. Resolves rt.cpan.org ticket 1648.
386 49 50       3976 if (tied *STDIN) {
387 0         0 carp "Cannot redirect out of tied STDIN. Untying it";
388 0         0 untie *STDIN;
389             }
390              
391 49 50       2996 if (tied *STDOUT) {
392 0         0 carp "Cannot redirect into tied STDOUT. Untying it";
393 0         0 untie *STDOUT;
394             }
395              
396 49 100       4085 if (tied *STDERR) {
397 1         1584 carp "Cannot redirect into tied STDERR. Untying it";
398 1         380 untie *STDERR;
399             }
400              
401             # If running pty, we delay the slave side creation 'til after
402             # doing the necessary bits to become our own [unix] session.
403 49 100       3744 if ($conduit =~ /^pty(-pipe)?$/) {
404              
405             # Become a new unix session.
406             # Program 19.3, APITUE. W. Richard Stevens built my hot rod.
407             #eval 'setsid()' unless $no_setsid;
408              
409             # Acquire a controlling terminal. Program 19.3, APITUE.
410 4         454 $stdin_write->make_slave_controlling_terminal();
411              
412             # Open the slave side of the pty.
413 4         5252 $stdin_read = $stdout_write = $stdin_write->slave();
414 4 50       199 __PACKAGE__->_warn_and_exit_child( "could not create slave pty: $!", int( $! ) )
415             unless defined $stdin_read;
416              
417             # For a simple pty conduit, stderr is wedged into stdout.
418 4 100       161 $stderr_write = $stdout_write if $conduit eq 'pty';
419              
420             # Put the pty conduit (slave side) into "raw" or "cbreak" mode,
421             # per APITUE 19.4 and 11.10.
422 4         199 $stdin_read->set_raw();
423              
424 4         6425 if (TIOCSWINSZ_AVAILABLE) {
425 4 50       116 if ($winsize) {
426 0         0 ioctl($stdin_read, TIOCSWINSZ, pack('vvvv', @$winsize));
427             }
428             }
429             else {
430             # Set the pty conduit (slave side) window size to our window
431             # size. APITUE 19.4 and 19.5.
432              
433             eval { $stdin_read->clone_winsize_from(\*STDIN) } if -T STDIN;
434             }
435             }
436             else {
437             # TODO - Can this be block eval? Or a do{} block?
438 45 50       80569 eval 'setpgrp(0,0)' unless $no_setpgrp;
439             }
440              
441             # Reset all signals in the child process. POE's own handlers are
442             # silly to keep around in the child process since POE won't be
443             # using them.
444 49         3683 my @safe_signals = $poe_kernel->_data_sig_get_safe_signals();
445 49         36097 @SIG{@safe_signals} = ("DEFAULT") x @safe_signals;
446 49 50       3744 $poe_kernel->_data_sig_unmask_all if $must_unmask;
447              
448             # TODO How to pass events to the parent process? Maybe over a
449             # expedited (OOB) filehandle.
450              
451             # Fix the child process' priority. Don't bother doing this if it
452             # wasn't requested. Can't emit events on failure because we're in
453             # a separate process, so just fail quietly.
454              
455 49 50       892 if ($priority_delta) {
456 0         0 eval {
457 0 0       0 if (defined(my $priority = getpriority(0, $$))) {
458 0 0       0 unless (setpriority(0, $$, $priority + $priority_delta)) {
459             # TODO can't set child priority
460             }
461             }
462             else {
463             # TODO can't get child priority
464             }
465             };
466 0 0       0 if ($@) {
467             # TODO can't get child priority
468             }
469             }
470              
471             # Fix the group ID. TODO Add getgrnam so group IDs can be
472             # specified by name. TODO Warn if not superuser to begin with.
473 49 50       863 if (defined $group_id) {
474 0         0 $( = $) = $group_id;
475             }
476              
477             # Fix the user ID. TODO Add getpwnam so user IDs can be specified
478             # by name. TODO Warn if not superuser to begin with.
479 49 50       1481 if (defined $user_id) {
480 0         0 $< = $> = $user_id;
481             }
482              
483             # Close what the child won't need.
484 49 100       1703 close $stdin_write if defined $stdin_write;
485 49 100       1168 close $stdout_read if defined $stdout_read;
486 49 100       1165 close $stderr_read if defined $stderr_read;
487              
488 49 50       924 if (POE::Kernel::RUNNING_IN_HELL) {
489 0         0 __PACKAGE__->_redirect_child_stdio_in_hell(
490             $stdin_read, $stdout_write, $stderr_write
491             );
492             }
493              
494             else {
495 49         3351 __PACKAGE__->_redirect_child_stdio_sanely(
496             $stdin_read, $stdout_write, $stderr_write
497             );
498             }
499              
500             # Make STDOUT and/or STDERR auto-flush.
501 49         680 select STDERR; $| = 1;
  49         441  
502 49         381 select STDOUT; $| = 1;
  49         508  
503              
504             # The child doesn't need to read from the semaphore pipe.
505 49         1459 $sem_pipe_read = undef;
506              
507             # Run Perl code. This is fairly consistent across most systems.
508              
509 49 100       1194 if (ref($program) eq 'CODE') {
510              
511             # Tell the parent that the stdio has been set up.
512 2         123 print $sem_pipe_write "go\n";
513 2         26 close $sem_pipe_write;
514              
515             # Close any close-on-exec file descriptors. Except STDIN,
516             # STDOUT, and STDERR, of course.
517 2 50       31 if ($close_on_call) {
518 0         0 for (0..MAX_OPEN_FDS-1) {
519 0 0       0 next if fileno(STDIN) == $_;
520 0 0       0 next if fileno(STDOUT) == $_;
521 0 0       0 next if fileno(STDERR) == $_;
522 0         0 POSIX::close($_);
523             }
524             }
525              
526             # TODO what if the program tries to exit? It needs to use
527             # our _exit_child_any_way_we_can handler...
528             # Should we replace CORE::exit? CORE::die too? blahhhhhh
529             # We've documented that users should not do it, but who knows!
530 2         8 eval { $program->(@$prog_args) };
  2         31  
531              
532 0         0 my $exitval;
533 0 0       0 if ($@) {
534 0         0 chomp $@;
535 0         0 warn "$@\n";
536 0         0 $exitval = -1;
537             }
538              
539 0   0     0 __PACKAGE__->_exit_child_any_way_we_can( $exitval || 0 );
540             }
541              
542             # Execute an external program. This gets weird.
543              
544             # Windows! What I do for you!
545             __PACKAGE__->_exec_in_hell(
546 47 50       568 $close_on_call, $sem_pipe_write, $program, $prog_args
547             ) if POE::Kernel::RUNNING_IN_HELL;
548              
549             # Everybody else seems sane.
550             # Tell the parent that the stdio has been set up.
551 47         2072 print $sem_pipe_write "go\n";
552 47         39187 close $sem_pipe_write;
553              
554             # exec(ARRAY)
555 47 50       1420 if (ref($program) eq 'ARRAY') {
556 47 0       0 exec(@$program, @$prog_args)
557             or __PACKAGE__->_warn_and_exit_child(
558             "can't exec (@$program) in child pid $$: $!", int( $! ) );
559             }
560              
561             # exec(SCALAR)
562 0 0       0 exec(join(" ", $program, @$prog_args))
563             or __PACKAGE__->_warn_and_exit_child(
564             "can't exec ($program) in child pid $$: $!", int( $! ) );
565             }
566              
567             # Parent here. Close what the parent won't need.
568              
569 266 100       17165 defined($stdin_read) and close $stdin_read;
570 266 100       7055 defined($stdout_write) and close $stdout_write;
571 266 100       4648 defined($stderr_write) and close $stderr_write;
572              
573              
574              
575             # Also close any slave ptys
576 266 100 100     23461 $stdout_read->close_slave() if (
577             defined $stdout_read and ref($stdout_read) eq 'IO::Pty'
578             );
579              
580 266 50 66     11875 $stderr_read->close_slave() if (
581             defined $stderr_read and ref($stderr_read) eq 'IO::Pty'
582             );
583              
584 266         1539 my $active_count = 0;
585 266 100 66     5076 $active_count++ if $stdout_event and $stdout_read;
586 266 100 66     4084 $active_count++ if $stderr_event and $stderr_read;
587              
588 266         26720 my $self = bless [
589             &POE::Wheel::allocate_wheel_id(), # UNIQUE_ID
590             $error_event, # ERROR_EVENT
591             $close_event, # CLOSE_EVENT
592             $program, # PROGRAM
593             $pid, # CHILD_PID
594             $conduit, # CONDUIT_TYPE
595             $active_count, # IS_ACTIVE
596             $close_on_call, # CLOSE_ON_CALL
597             $stdio_type, # STDIO_TYPE
598             # STDIN
599             $stdin_write, # HANDLE_STDIN
600             $stdin_filter, # FILTER_STDIN
601             $stdin_driver, # DRIVER_STDIN
602             $stdin_event, # EVENT_STDIN
603             undef, # STATE_STDIN
604             0, # OCTETS_STDIN
605             # STDOUT
606             $stdout_read, # HANDLE_STDOUT
607             $stdout_filter, # FILTER_STDOUT
608             $stdout_driver, # DRIVER_STDOUT
609             $stdout_event, # EVENT_STDOUT
610             undef, # STATE_STDOUT
611             # STDERR
612             $stderr_read, # HANDLE_STDERR
613             $stderr_filter, # FILTER_STDERR
614             $stderr_driver, # DRIVER_STDERR
615             $stderr_event, # EVENT_STDERR
616             undef, # STATE_STDERR
617             undef, # MSWIN32_GROUP_PID
618             ], $type;
619              
620             # PG- I suspect <> might need PIPE
621 266 50       15432 $poe_kernel->_data_sig_unmask_all if $must_unmask;
622              
623             # Wait here while the child sets itself up.
624 266         16041 $sem_pipe_write = undef;
625             {
626 266         3965 local $/ = "\n"; # TODO - Needed?
  266         11391  
627 266         1099144 my $chldout = <$sem_pipe_read>;
628 266         1955 chomp $chldout;
629 266 50       2659 $self->[MSWIN32_GROUP_PID] = $chldout if $chldout ne 'go';
630             }
631 266         6439 close $sem_pipe_read;
632              
633 266 100       11577 $self->_define_stdin_flusher() if defined $stdin_write;
634 266 100       4055 $self->_define_stdout_reader() if defined $stdout_read;
635 266 100       3131 $self->_define_stderr_reader() if defined $stderr_read;
636              
637 266         15342 return $self;
638             }
639              
640             #------------------------------------------------------------------------------
641             # Define the internal state that will flush output to the child
642             # process' STDIN pipe.
643              
644             sub _define_stdin_flusher {
645 262     262   2170 my $self = shift;
646              
647             # Read-only members. If any of these change, then the write state
648             # is invalidated and needs to be redefined.
649 262         3240 my $unique_id = $self->[UNIQUE_ID];
650 262         652 my $driver = $self->[DRIVER_STDIN];
651 262         771 my $error_event = \$self->[ERROR_EVENT];
652 262         662 my $close_event = \$self->[CLOSE_EVENT];
653 262         702 my $stdin_filter = $self->[FILTER_STDIN];
654 262         727 my $stdin_event = \$self->[EVENT_STDIN];
655 262         569 my $is_active = \$self->[IS_ACTIVE];
656              
657             # Read/write members. These are done by reference, to avoid pushing
658             # $self into the anonymous sub. Extra copies of $self are bad and
659             # can prevent wheels from destructing properly.
660 262         844 my $stdin_octets = \$self->[OCTETS_STDIN];
661              
662             # Register the select-write handler.
663             $poe_kernel->state(
664             $self->[STATE_STDIN] = ref($self) . "($unique_id) -> select stdin",
665             sub { # prevents SEGV
666 146     146   206 0 && CRIMSON_SCOPE_HACK('<');
667             # subroutine starts here
668 146         414 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
669              
670 146         3121 $$stdin_octets = $driver->flush($handle);
671              
672             # When you can't write, nothing else matters.
673 146 50       834 if ($!) {
674 0 0       0 $$error_event && $k->call(
675             $me, $$error_event,
676             'write', ($!+0), $!, $unique_id, "STDIN"
677             );
678 0         0 $k->select_write($handle);
679             }
680              
681             # Could write, or perhaps couldn't but only because the
682             # filehandle's buffer is choked.
683             else {
684              
685             # All chunks written; fire off a "flushed" event.
686 146 50       327 unless ($$stdin_octets) {
687 146         931 $k->select_pause_write($handle);
688 146 100       653 $$stdin_event && $k->call($me, $$stdin_event, $unique_id);
689             }
690             }
691             }
692 262         24185 );
693              
694 262         8328 $poe_kernel->select_write($self->[HANDLE_STDIN], $self->[STATE_STDIN]);
695              
696             # Pause the write select immediately, unless output is pending.
697 262 50       3943 $poe_kernel->select_pause_write($self->[HANDLE_STDIN])
698             unless ($self->[OCTETS_STDIN]);
699             }
700              
701             #------------------------------------------------------------------------------
702             # Define the internal state that will read input from the child
703             # process' STDOUT pipe. This is virtually identical to
704             # _define_stderr_reader, but they aren't implemented as a common
705             # function for speed reasons.
706              
707             sub _define_stdout_reader {
708 259     259   527 my $self = shift;
709              
710             # Can't do anything if we don't have a handle.
711 259 50       822 return unless defined $self->[HANDLE_STDOUT];
712              
713             # No event? Unregister the handler and leave.
714 259         897 my $stdout_event = \$self->[EVENT_STDOUT];
715 259 50       755 unless ($$stdout_event) {
716 0         0 $poe_kernel->select_read($self->[HANDLE_STDOUT]);
717 0         0 return;
718             }
719              
720             # If any of these change, then the read state is invalidated and
721             # needs to be redefined.
722 259         681 my $unique_id = $self->[UNIQUE_ID];
723 259         433 my $driver = $self->[DRIVER_STDOUT];
724 259         496 my $stdout_filter = $self->[FILTER_STDOUT];
725              
726             # These can change without redefining the callback since they're
727             # enclosed by reference.
728 259         590 my $is_active = \$self->[IS_ACTIVE];
729 259         661 my $close_event = \$self->[CLOSE_EVENT];
730 259         670 my $error_event = \$self->[ERROR_EVENT];
731              
732             # Register the select-read handler for STDOUT.
733 259 100 66     17168 if (
734             $stdout_filter->can("get_one") and
735             $stdout_filter->can("get_one_start")
736             ) {
737             $poe_kernel->state(
738             $self->[STATE_STDOUT] = ref($self) . "($unique_id) -> select stdout",
739             sub {
740             # prevents SEGV
741 208     208   351 0 && CRIMSON_SCOPE_HACK('<');
742              
743             # subroutine starts here
744 208         848 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
745 208 100       2270 if (defined(my $raw_input = $driver->get($handle))) {
746 57         344 $stdout_filter->get_one_start($raw_input);
747 57         79 while (1) {
748 114         346 my $next_rec = $stdout_filter->get_one();
749 114 100       485 last unless @$next_rec;
750 57         117 foreach my $cooked_input (@$next_rec) {
751 57         313 $k->call($me, $$stdout_event, $cooked_input, $unique_id);
752             }
753             }
754             }
755             else {
756 151 100       1198 $$error_event and $k->call(
757             $me, $$error_event,
758             'read', ($!+0), $!, $unique_id, 'STDOUT'
759             );
760 151 100       729 unless (--$$is_active) {
761 117 100       682 $k->call( $me, $$close_event, $unique_id )
762             if defined $$close_event;
763             }
764 151         717 $k->select_read($handle);
765             }
766             }
767 223         7824 );
768             }
769              
770             # Otherwise we can't get one.
771             else {
772             $poe_kernel->state(
773             $self->[STATE_STDOUT] = ref($self) . "($unique_id) -> select stdout",
774             sub {
775             # prevents SEGV
776 26     26   55 0 && CRIMSON_SCOPE_HACK('<');
777              
778             # subroutine starts here
779 26         103 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
780 26 100       151 if (defined(my $raw_input = $driver->get($handle))) {
781 16         25 foreach my $cooked_input (@{$stdout_filter->get($raw_input)}) {
  16         76  
782 16         67 $k->call($me, $$stdout_event, $cooked_input, $unique_id);
783             }
784             }
785             else {
786 10 50       103 $$error_event and
787             $k->call(
788             $me, $$error_event,
789             'read', ($!+0), $!, $unique_id, 'STDOUT'
790             );
791 10 100       54 unless (--$$is_active) {
792 8 50       62 $k->call( $me, $$close_event, $unique_id )
793             if defined $$close_event;
794             }
795 10         70 $k->select_read($handle);
796             }
797             }
798 36         1492 );
799             }
800              
801             # register the state's select
802 259         3370 $poe_kernel->select_read($self->[HANDLE_STDOUT], $self->[STATE_STDOUT]);
803             }
804              
805             #------------------------------------------------------------------------------
806             # Define the internal state that will read input from the child
807             # process' STDERR pipe.
808              
809             sub _define_stderr_reader {
810 175     175   656 my $self = shift;
811              
812             # Can't do anything if we don't have a handle.
813 175 50       622 return unless defined $self->[HANDLE_STDERR];
814              
815             # No event? Unregister the handler and leave.
816 175         595 my $stderr_event = \$self->[EVENT_STDERR];
817 175 50       454 unless ($$stderr_event) {
818 0         0 $poe_kernel->select_read($self->[HANDLE_STDERR]);
819 0         0 return;
820             }
821              
822 175         364 my $unique_id = $self->[UNIQUE_ID];
823 175         284 my $driver = $self->[DRIVER_STDERR];
824 175         280 my $stderr_filter = $self->[FILTER_STDERR];
825              
826             # These can change without redefining the callback since they're
827             # enclosed by reference.
828 175         350 my $error_event = \$self->[ERROR_EVENT];
829 175         399 my $close_event = \$self->[CLOSE_EVENT];
830 175         394 my $is_active = \$self->[IS_ACTIVE];
831              
832             # Register the select-read handler for STDERR.
833 175 100 66     6366 if (
834             $stderr_filter->can("get_one") and
835             $stderr_filter->can("get_one_start")
836             ) {
837             $poe_kernel->state(
838             $self->[STATE_STDERR] = ref($self) . "($unique_id) -> select stderr",
839             sub {
840             # prevents SEGV
841 92     92   169 0 && CRIMSON_SCOPE_HACK('<');
842              
843             # subroutine starts here
844 92         360 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
845 92 100       491 if (defined(my $raw_input = $driver->get($handle))) {
846 16         83 $stderr_filter->get_one_start($raw_input);
847 16         24 while (1) {
848 32         127 my $next_rec = $stderr_filter->get_one();
849 32 100       180 last unless @$next_rec;
850 16         48 foreach my $cooked_input (@$next_rec) {
851 16         107 $k->call($me, $$stderr_event, $cooked_input, $unique_id);
852             }
853             }
854             }
855             else {
856 76 100       620 $$error_event and $k->call(
857             $me, $$error_event,
858             'read', ($!+0), $!, $unique_id, 'STDERR'
859             );
860 76 100       195 unless (--$$is_active) {
861 34 100       149 $k->call( $me, $$close_event, $unique_id )
862             if defined $$close_event;
863             }
864 76         290 $k->select_read($handle);
865             }
866             }
867 149         3764 );
868             }
869              
870             # Otherwise we can't get_one().
871             else {
872             $poe_kernel->state(
873             $self->[STATE_STDERR] = ref($self) . "($unique_id) -> select stderr",
874             sub {
875             # prevents SEGV
876 10     10   20 0 && CRIMSON_SCOPE_HACK('<');
877              
878             # subroutine starts here
879 10         37 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
880 10 100       46 if (defined(my $raw_input = $driver->get($handle))) {
881 4         7 foreach my $cooked_input (@{$stderr_filter->get($raw_input)}) {
  4         18  
882 4         18 $k->call($me, $$stderr_event, $cooked_input, $unique_id);
883             }
884             }
885             else {
886 6 50       57 $$error_event and $k->call(
887             $me, $$error_event,
888             'read', ($!+0), $!, $unique_id, 'STDERR'
889             );
890 6 100       27 unless (--$$is_active) {
891 2 50       14 $k->call( $me, $$close_event, $unique_id )
892             if defined $$close_event;
893             }
894 6         29 $k->select_read($handle);
895             }
896             }
897 26         659 );
898             }
899              
900             # Register the state's select.
901 175         1428 $poe_kernel->select_read($self->[HANDLE_STDERR], $self->[STATE_STDERR]);
902             }
903              
904             #------------------------------------------------------------------------------
905             # Redefine events.
906              
907             sub event {
908 164     164 1 2641 my $self = shift;
909 164 50       743 push(@_, undef) if (scalar(@_) & 1);
910              
911 164         411 my ($redefine_stdin, $redefine_stdout, $redefine_stderr) = (0, 0, 0);
912              
913 164         346 while (@_) {
914 400         787 my ($name, $event) = splice(@_, 0, 2);
915              
916 400 100       1075 if ($name eq 'StdinEvent') {
    100          
    100          
    100          
    50          
917 82         142 $self->[EVENT_STDIN] = $event;
918 82         178 $redefine_stdin = 1;
919             }
920             elsif ($name eq 'StdoutEvent') {
921 82         173 $self->[EVENT_STDOUT] = $event;
922 82         247 $redefine_stdout = 1;
923             }
924             elsif ($name eq 'StderrEvent') {
925 72 50       166 if ($self->[CONDUIT_TYPE] ne 'pty') {
926 72         798 $self->[EVENT_STDERR] = $event;
927 72         144 $redefine_stderr = 1;
928             }
929             else {
930 0         0 carp "ignoring StderrEvent on a pty conduit";
931             }
932             }
933             elsif ($name eq 'ErrorEvent') {
934 82         202 $self->[ERROR_EVENT] = $event;
935             }
936             elsif ($name eq 'CloseEvent') {
937 82         189 $self->[CLOSE_EVENT] = $event;
938             }
939             else {
940 0         0 carp "ignoring unknown Run parameter '$name'";
941             }
942             }
943              
944             # Recalculate the active handles count.
945 164         208 my $active_count = 0;
946 164 50 33     1469 $active_count++ if $self->[EVENT_STDOUT] and $self->[HANDLE_STDOUT];
947 164 50 66     696 $active_count++ if $self->[EVENT_STDERR] and $self->[HANDLE_STDERR];
948 164         524 $self->[IS_ACTIVE] = $active_count;
949             }
950              
951             #------------------------------------------------------------------------------
952             # Destroy the wheel.
953              
954             sub DESTROY {
955 203     203   39415 my $self = shift;
956              
957 203 100       40599 return if(ref POE::Kernel->get_active_session eq 'POE::Kernel');
958              
959             # Turn off the STDIN thing.
960 201 100       726 if ($self->[HANDLE_STDIN]) {
961 197         1301 $poe_kernel->select_write($self->[HANDLE_STDIN]);
962 197         4890 $self->[HANDLE_STDIN] = undef;
963             }
964              
965 201 100       677 if ($self->[STATE_STDIN]) {
966 199         990 $poe_kernel->state($self->[STATE_STDIN]);
967 199         382 $self->[STATE_STDIN] = undef;
968             }
969              
970 201 100       522 if ($self->[HANDLE_STDOUT]) {
971 196         686 $poe_kernel->select_read($self->[HANDLE_STDOUT]);
972 196         2455 $self->[HANDLE_STDOUT] = undef;
973             }
974 201 100       698 if ($self->[STATE_STDOUT]) {
975 196         779 $poe_kernel->state($self->[STATE_STDOUT]);
976 196         419 $self->[STATE_STDOUT] = undef;
977             }
978              
979 201 100       698 if ($self->[HANDLE_STDERR]) {
980 118         457 $poe_kernel->select_read($self->[HANDLE_STDERR]);
981 118         1376 $self->[HANDLE_STDERR] = undef;
982             }
983 201 100       796 if ($self->[STATE_STDERR]) {
984 118         349 $poe_kernel->state($self->[STATE_STDERR]);
985 118         276 $self->[STATE_STDERR] = undef;
986             }
987              
988 201         1225 &POE::Wheel::free_wheel_id($self->[UNIQUE_ID]);
989             }
990              
991             #------------------------------------------------------------------------------
992             # Queue input for the child process.
993              
994             sub put {
995 224     224 1 10647 my ($self, @chunks) = @_;
996              
997             # Avoid big bada boom if someone put()s on a dead wheel.
998 224 100       1138 croak "Called put() on a wheel without an open STDIN handle" unless (
999             $self->[HANDLE_STDIN]
1000             );
1001              
1002 222 50       5194 if (
1003             $self->[OCTETS_STDIN] = # assignment on purpose
1004             $self->[DRIVER_STDIN]->put($self->[FILTER_STDIN]->put(\@chunks))
1005             ) {
1006 222         2089 $poe_kernel->select_resume_write($self->[HANDLE_STDIN]);
1007             }
1008              
1009             # No watermark.
1010 222         749 return 0;
1011             }
1012              
1013             #------------------------------------------------------------------------------
1014             # Pause and resume various input events.
1015              
1016             sub pause_stdout {
1017 2     2 1 9288 my $self = shift;
1018 2 50       8 return unless defined $self->[HANDLE_STDOUT];
1019 2         13 $poe_kernel->select_pause_read($self->[HANDLE_STDOUT]);
1020             }
1021              
1022             sub pause_stderr {
1023 2     2 1 4409 my $self = shift;
1024 2 50       8 return unless defined $self->[HANDLE_STDERR];
1025 2         9 $poe_kernel->select_pause_read($self->[HANDLE_STDERR]);
1026             }
1027              
1028             sub resume_stdout {
1029 2     2 1 884 my $self = shift;
1030 2 50       8 return unless defined $self->[HANDLE_STDOUT];
1031 2         9 $poe_kernel->select_resume_read($self->[HANDLE_STDOUT]);
1032             }
1033              
1034             sub resume_stderr {
1035 2     2 1 4450 my $self = shift;
1036 2 50       8 return unless defined $self->[HANDLE_STDERR];
1037 2         8 $poe_kernel->select_resume_read($self->[HANDLE_STDERR]);
1038             }
1039              
1040             # Shutdown the pipe that leads to the child's STDIN.
1041             sub shutdown_stdin {
1042 2     2 1 7090 my $self = shift;
1043 2 50       13 return unless defined $self->[HANDLE_STDIN];
1044              
1045 2         20 $poe_kernel->select_write($self->[HANDLE_STDIN], undef);
1046              
1047 2         7 eval { local $^W = 0; shutdown($self->[HANDLE_STDIN], 1) };
  2         11  
  2         17  
1048 2 50 33     23 if ($@ or $self->[HANDLE_STDIN] != $self->[HANDLE_STDOUT]) {
1049 2         16 close $self->[HANDLE_STDIN];
1050             }
1051              
1052 2         61 $self->[HANDLE_STDIN] = undef;
1053             }
1054              
1055             #------------------------------------------------------------------------------
1056             # Redefine filters, one at a time or at once. This is based on PG's
1057             # code in Wheel::ReadWrite.
1058              
1059             sub _transfer_stdout_buffer {
1060 0     0   0 my ($self, $buf) = @_;
1061              
1062 0         0 my $old_output_filter = $self->[FILTER_STDOUT];
1063              
1064             # Assign old buffer contents to the new filter, and send out any
1065             # pending packets.
1066              
1067             # Use "get_one" if the new filter implements it.
1068 0 0       0 if (defined $buf) {
1069 0 0 0     0 if (
1070             $old_output_filter->can("get_one") and
1071             $old_output_filter->can("get_one_start")
1072             ) {
1073 0         0 $old_output_filter->get_one_start($buf);
1074              
1075             # Don't bother to continue if the filter has switched out from
1076             # under our feet again. The new switcher will finish the job.
1077              
1078 0         0 while ($self->[FILTER_STDOUT] == $old_output_filter) {
1079 0         0 my $next_rec = $old_output_filter->get_one();
1080 0 0       0 last unless @$next_rec;
1081 0         0 foreach my $cooked_input (@$next_rec) {
1082 0         0 $poe_kernel->call(
1083             $poe_kernel->get_active_session(), $self->[EVENT_STDOUT],
1084             $cooked_input, $self->[UNIQUE_ID]
1085             );
1086             }
1087             }
1088             }
1089              
1090             # Otherwise use the old get() behavior.
1091             else {
1092 0         0 foreach my $cooked_input (@{$self->[FILTER_STDOUT]->get($buf)}) {
  0         0  
1093 0         0 $poe_kernel->call(
1094             $poe_kernel->get_active_session(), $self->[EVENT_STDOUT],
1095             $cooked_input, $self->[UNIQUE_ID]
1096             );
1097             }
1098             }
1099             }
1100             }
1101              
1102             sub _transfer_stderr_buffer {
1103 0     0   0 my ($self, $buf) = @_;
1104              
1105 0         0 my $old_output_filter = $self->[FILTER_STDERR];
1106              
1107             # Assign old buffer contents to the new filter, and send out any
1108             # pending packets.
1109              
1110             # Use "get_one" if the new filter implements it.
1111 0 0       0 if (defined $buf) {
1112 0 0 0     0 if (
1113             $old_output_filter->can("get_one") and
1114             $old_output_filter->can("get_one_start")
1115             ) {
1116 0         0 $old_output_filter->get_one_start($buf);
1117              
1118             # Don't bother to continue if the filter has switched out from
1119             # under our feet again. The new switcher will finish the job.
1120              
1121 0         0 while ($self->[FILTER_STDERR] == $old_output_filter) {
1122 0         0 my $next_rec = $old_output_filter->get_one();
1123 0 0       0 last unless @$next_rec;
1124 0         0 foreach my $cooked_input (@$next_rec) {
1125 0         0 $poe_kernel->call(
1126             $poe_kernel->get_active_session(), $self->[EVENT_STDERR],
1127             $cooked_input, $self->[UNIQUE_ID]
1128             );
1129             }
1130             }
1131             }
1132              
1133             # Otherwise use the old get() behavior.
1134             else {
1135 0         0 foreach my $cooked_input (@{$self->[FILTER_STDERR]->get($buf)}) {
  0         0  
1136 0         0 $poe_kernel->call(
1137             $poe_kernel->get_active_session(), $self->[EVENT_STDERR],
1138             $cooked_input, $self->[UNIQUE_ID]
1139             );
1140             }
1141             }
1142             }
1143             }
1144              
1145             sub set_stdio_filter {
1146 0     0 1 0 my ($self, $new_filter) = @_;
1147 0         0 $self->set_stdout_filter($new_filter);
1148 0         0 $self->set_stdin_filter($new_filter);
1149             }
1150              
1151             sub set_stdin_filter {
1152 0     0 1 0 my ($self, $new_filter) = @_;
1153 0         0 $self->[FILTER_STDIN] = $new_filter;
1154             }
1155              
1156             sub set_stdout_filter {
1157 0     0 1 0 my ($self, $new_filter) = @_;
1158              
1159 0         0 my $buf = $self->[FILTER_STDOUT]->get_pending();
1160 0         0 $self->[FILTER_STDOUT] = $new_filter;
1161              
1162 0         0 $self->_transfer_stdout_buffer($buf);
1163             }
1164              
1165             sub set_stderr_filter {
1166 0     0 1 0 my ($self, $new_filter) = @_;
1167              
1168 0         0 my $buf = $self->[FILTER_STDERR]->get_pending();
1169 0         0 $self->[FILTER_STDERR] = $new_filter;
1170              
1171 0         0 $self->_transfer_stderr_buffer($buf);
1172             }
1173              
1174             sub get_stdin_filter {
1175 0     0 1 0 my $self = shift;
1176 0         0 return $self->[FILTER_STDIN];
1177             }
1178              
1179             sub get_stdout_filter {
1180 0     0 1 0 my $self = shift;
1181 0         0 return $self->[FILTER_STDOUT];
1182             }
1183              
1184             sub get_stderr_filter {
1185 0     0 1 0 my $self = shift;
1186 0         0 return $self->[FILTER_STDERR];
1187             }
1188              
1189             #------------------------------------------------------------------------------
1190             # Data accessors.
1191              
1192             sub get_driver_out_octets {
1193 20     20 1 20456 $_[0]->[OCTETS_STDIN];
1194             }
1195              
1196             sub get_driver_out_messages {
1197 20     20 1 138 $_[0]->[DRIVER_STDIN]->get_out_messages_buffered();
1198             }
1199              
1200             sub ID {
1201 170     170 1 5465 $_[0]->[UNIQUE_ID];
1202             }
1203              
1204             sub PID {
1205 311     311 1 36092 $_[0]->[CHILD_PID];
1206             }
1207              
1208             sub kill {
1209 4     4 1 10429 my ($self, $signal) = @_;
1210 4 50       49 $signal = 'TERM' unless defined $signal;
1211 4 50       16 if ( $self->[MSWIN32_GROUP_PID] ) {
1212             # TODO use https://rt.cpan.org/Ticket/Display.html?id=67774 when available :)
1213 0 0       0 Win32::Process::KillProcess( $self->[MSWIN32_GROUP_PID], 293 ) ? 1 : 0;
1214             }
1215             else {
1216 4         8 eval { kill $signal, $self->[CHILD_PID] };
  4         129  
1217             }
1218             }
1219              
1220             ### Internal helpers.
1221              
1222             sub _redirect_child_stdio_in_hell {
1223 0     0   0 my ($class, $stdin_read, $stdout_write, $stderr_write) = @_;
1224              
1225             # Win32 needs the stdio handles closed before they're reopened
1226             # because the standard handles aren't dup()'d.
1227              
1228 0         0 close STDIN;
1229 0         0 close STDOUT;
1230 0         0 close STDERR;
1231              
1232 0         0 $class->_redirect_child_stdio_sanely(
1233             $stdin_read, $stdout_write, $stderr_write
1234             );
1235              
1236             # The Win32 pseudo fork sets up the std handles in the child
1237             # based on the true win32 handles. The reopening of stdio
1238             # handles isn't enough. We must also set the underlying
1239             # Win32 notion of these handles for completeness.
1240             #
1241             # Only necessary for the exec, as Perl CODE subroutine goes
1242             # through 0/1/2 which are correct. But of course that coderef
1243             # might invoke exec, so better do it regardless.
1244             #
1245             # HACK: Using Win32::Console as nothing else exposes
1246             # SetStdHandle
1247             #
1248             # TODO - https://rt.cpan.org/Ticket/Display.html?id=50068 claims
1249             # that these _SetStdHandle() calls may leak memory. Do we have
1250             # alternatives?
1251              
1252 0 0       0 Win32::Console::_SetStdHandle(
1253             $STD_INPUT_HANDLE,
1254             FdGetOsFHandle(fileno($stdin_read))
1255             ) if defined $stdin_read;
1256              
1257 0 0       0 Win32::Console::_SetStdHandle(
1258             $STD_OUTPUT_HANDLE,
1259             FdGetOsFHandle(fileno($stdout_write))
1260             ) if defined $stdout_write;
1261              
1262 0 0       0 Win32::Console::_SetStdHandle(
1263             $STD_ERROR_HANDLE,
1264             FdGetOsFHandle(fileno($stderr_write))
1265             ) if defined $stderr_write;
1266             }
1267              
1268             sub _filespec_to_fh {
1269 945     945   1855 my ($dest,$mode,$fspec) = @_;
1270 945 100       1633 return unless defined $fspec;
1271 12 50       78 if(ref $fspec) {
1272 12 50       68 if (ref $fspec eq 'GLOB') {
1273 12         350 open $$dest, "$mode&", $fspec;
1274             } else {
1275 0         0 die("Bad file specifier '$fspec'");
1276             }
1277             } else {
1278 0         0 open $$dest, $mode, $fspec;
1279             }
1280             }
1281              
1282             sub _redirect_child_stdio_sanely {
1283 49     49   590 my ($class, $stdin_read, $stdout_write, $stderr_write) = @_;
1284              
1285             # Note: we use 2-arg open() below because Perl 5.6 doesn't recognize
1286             # the '>&' and '<&' modes with a 3-arg open()
1287              
1288             # Redirect STDIN from the read end of the stdin pipe.
1289 49 50       812 if(defined $stdin_read) {
1290 49 50       2788 open( STDIN, "<&" . fileno($stdin_read) )
1291             or $class->_warn_and_exit_child(
1292             "can't redirect STDIN in child pid $$: $!", int( $! ) );
1293             }
1294              
1295             # Redirect STDOUT to the write end of the stdout pipe.
1296 49 100       1050 if(defined $stdout_write) {
1297 48 50       1549 open( STDOUT, ">&" . fileno($stdout_write) )
1298             or $class->_warn_and_exit_child(
1299             "can't redirect stdout in child pid $$: $!", int( $! ) );
1300             }
1301             # Redirect STDERR to the write end of the stderr pipe.
1302 49 100       787 if(defined $stderr_write) {
1303 33 50       948 open( STDERR, ">&" . fileno($stderr_write) )
1304             or $class->_warn_and_exit_child(
1305             "can't redirect stderr in child pid $$: $!", int( $! ) );
1306             }
1307             }
1308              
1309             sub _exit_child_any_way_we_can {
1310 0     0     my $class = shift;
1311 0   0       my $exitval = shift || 0;
1312              
1313             # First make sure stdio are flushed.
1314 0 0         close STDIN if defined fileno(STDIN); # Voodoo?
1315 0 0         close STDOUT if defined fileno(STDOUT);
1316 0 0         close STDERR if defined fileno(STDERR);
1317              
1318             # On Windows, subprocesses run in separate threads. All the "fancy"
1319             # methods act on entire processes, so they also exit the parent.
1320              
1321 0 0         unless (POE::Kernel::RUNNING_IN_HELL) {
1322             # Try to avoid triggering END blocks and object destructors.
1323 0           eval { POSIX::_exit( $exitval ); };
  0            
1324              
1325             # TODO those methods will not exit with $exitval... what to do?
1326 0           eval { CORE::kill KILL => $$; };
  0            
1327 0           eval { exec("$^X -e 0"); };
  0            
1328             } else {
1329 0           eval { CORE::kill( KILL => $$ ); };
  0            
1330              
1331             # TODO Interestingly enough, the KILL is not enough to terminate this process...
1332             # However, it *is* enough to stop execution of END blocks/etc
1333             # So we will end up falling through to the exit( $exitval ) below
1334             }
1335              
1336             # Do what we must.
1337 0           exit( $exitval );
1338             }
1339              
1340             # RUNNING_IN_HELL use Win32::Process to create a pucker new shiny
1341             # process. It'll inherit our processes handles which is neat.
1342              
1343             sub _exec_in_hell {
1344             my (
1345 0     0     $class, $close_on_call, $sem_pipe_write,
1346             $program, $prog_args
1347             ) = @_;
1348              
1349             # Close any close-on-exec file descriptors.
1350             # Except STDIN, STDOUT, and STDERR, of course.
1351              
1352 0 0         if ($close_on_call) {
1353 0           for (0..MAX_OPEN_FDS-1) {
1354 0 0         next if fileno(STDIN) == $_;
1355 0 0         next if fileno(STDOUT) == $_;
1356 0 0         next if fileno(STDERR) == $_;
1357 0           POSIX::close($_);
1358             }
1359             }
1360              
1361 0           my ($appname, $cmdline);
1362              
1363 0 0         if (ref $program eq 'ARRAY') {
1364 0           $appname = $program->[0];
1365             $cmdline = join(
1366             ' ',
1367 0 0 0       map { /\s/ && ! /"/ ? qq{"$_"} : $_ }
  0            
1368             (@$program, @$prog_args)
1369             );
1370             }
1371             else {
1372 0           $appname = undef;
1373             $cmdline = join(
1374             ' ', $program,
1375 0 0 0       map { /\s/ && ! /"/ ? qq{"$_"} : $_ }
  0            
1376             @$prog_args
1377             );
1378             }
1379              
1380 0           my $w32job;
1381              
1382 0 0         unless ( $w32job = Win32::Job->new() ) {
1383 0           print $sem_pipe_write "go\n\n"; # TODO why the double newline?
1384 0           close $sem_pipe_write;
1385 0           $class->_warn_and_exit_child(
1386             Win32::FormatMessage( Win32::GetLastError() ), Win32::GetLastError() );
1387             }
1388              
1389 0           my $w32pid;
1390              
1391 0 0         unless ( $w32pid = $w32job->spawn( $appname, $cmdline ) ) {
1392 0           print $sem_pipe_write "go\n";
1393 0           close $sem_pipe_write;
1394 0           $class->_warn_and_exit_child(
1395             Win32::FormatMessage( Win32::GetLastError() ), Win32::GetLastError() );
1396             }
1397              
1398 0           print $sem_pipe_write "$w32pid\n";
1399 0           close $sem_pipe_write;
1400              
1401             # TODO why 60? Why not MAX_INT so we don't do unnecessary work?
1402 0     0     my $ok = $w32job->watch( sub { 0 }, 60 );
  0            
1403 0           my $hashref = $w32job->status();
1404              
1405             # In case flushing them wasn't good enough.
1406 0 0         close STDOUT if defined fileno(STDOUT);
1407 0 0         close STDERR if defined fileno(STDERR);
1408              
1409 0           $class->_exit_child_any_way_we_can( $hashref->{$w32pid}->{exitcode} );
1410             }
1411              
1412             # Simple helper to ease the pain of warn+exit
1413             sub _warn_and_exit_child {
1414 0     0     my( $class, $warning, $exitval ) = @_;
1415              
1416 0           warn "$warning\n";
1417              
1418 0           $class->_exit_child_any_way_we_can( $exitval );
1419             }
1420              
1421             1;
1422              
1423             __END__