File Coverage

blib/lib/POE/Wheel/Run.pm
Criterion Covered Total %
statement 377 562 67.0
branch 216 384 56.2
condition 77 157 49.0
subroutine 30 45 66.6
pod 20 21 95.2
total 720 1169 61.5


line stmt bran cond sub pod time code
1             package POE::Wheel::Run;
2              
3 72     72   19884 use strict;
  72         94  
  72         2499  
4              
5 72     72   234 use vars qw($VERSION @ISA);
  72         93  
  72         3885  
6             $VERSION = '1.366'; # NOTE - Should be #.### (three decimal places)
7              
8 72     72   249 use Carp qw(carp croak);
  72         90  
  72         3861  
9 72         464 use POSIX qw(
10             sysconf setsid _SC_OPEN_MAX ECHO ICANON IEXTEN ISIG BRKINT ICRNL
11             INPCK ISTRIP IXON CSIZE PARENB OPOST TCSANOW
12 72     72   308 );
  72         215  
13              
14 72     72   8641 use POE qw( Wheel Pipe::TwoWay Pipe::OneWay Driver::SysRW Filter::Line );
  72         120  
  72         535  
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 72 50   72   363 die "$^O does not support fork()\n" if $^O eq 'MacOS';
25              
26 72         357 local $SIG{'__DIE__'} = 'DEFAULT';
27 72         100 eval { require IO::Pty; };
  72         34262  
28 72 50       329454 if ($@) {
29 0         0 eval '
30             sub PTY_AVAILABLE () { 0 }
31             sub TIOCSWINSZ_AVAILABLE () { 0 }
32             ';
33             }
34             else {
35 72         1690 IO::Pty->import();
36 72         2886 eval 'sub PTY_AVAILABLE () { 1 }';
37              
38 72         253 eval { require IO::Tty; };
  72         403  
39 72 50       507 if ($@) {
40 0         0 eval 'sub TIOCSWINSZ_AVAILABLE () { 0 }';
41             }
42             else {
43 72         296 IO::Tty->import('TIOCSWINSZ');
44 72         6326 eval 'sub TIOCSWINSZ_AVAILABLE () { 1 }';
45             }
46             }
47              
48 72 50       363 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 72         124 my $max_open_fds;
74 72         102 eval {
75 72         510 $max_open_fds = sysconf(_SC_OPEN_MAX);
76             };
77 72 50       246 $max_open_fds = 1024 unless $max_open_fds;
78 72         2079 eval "sub MAX_OPEN_FDS () { $max_open_fds }";
79 72 50       404989 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 363     363 1 6701 my $type = shift;
121 363 50       1030 croak "$type needs an even number of parameters" if @_ & 1;
122 363         2495 my %params = @_;
123              
124 363 50 33     2589 croak "wheels no longer require a kernel reference as their first parameter"
125             if @_ and ref($_[0]) eq 'POE::Kernel';
126              
127 363 50       860 croak "$type requires a working Kernel" unless defined $poe_kernel;
128              
129 363         1009 my $program = delete $params{Program};
130 363 100       2412 croak "$type needs a Program parameter" unless defined $program;
131              
132 348         551 my $prog_args = delete $params{ProgramArgs};
133 348 100       923 $prog_args = [] unless defined $prog_args;
134 348 50       1271 croak "ProgramArgs must be an ARRAY reference"
135             unless ref($prog_args) eq "ARRAY";
136              
137 348         598 my $priority_delta = delete $params{Priority};
138 348 50       956 $priority_delta = 0 unless defined $priority_delta;
139              
140 348         510 my $close_on_call = delete $params{CloseOnCall};
141 348 50       823 $close_on_call = 0 unless defined $close_on_call;
142              
143 348         591 my $user_id = delete $params{User};
144 348         506 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 348         578 my $conduit = delete $params{Conduit};
157 348         1154 my $stdio_type;
158 348 100       924 if (defined $conduit) {
159 64 100 100     2215 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 49 100       463 unless ($conduit =~ /^pty(-pipe)?$/) {
167 27         69 $stdio_type = $conduit;
168 27         76 $conduit = "pipe";
169             }
170             }
171             else {
172 284         477 $conduit = "pipe";
173             }
174              
175 333         547 my $winsize = delete $params{Winsize};
176              
177 333 50       715 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 333         629 my $stdin_event = delete $params{StdinEvent};
195 333         652 my $stdout_event = delete $params{StdoutEvent};
196 333         552 my $stderr_event = delete $params{StderrEvent};
197              
198 333 50 66     1168 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 333   33     3757 my $stdio_driver = delete $params{StdioDriver} || POE::Driver::SysRW->new();
207 333   33     1486 my $stdin_driver = delete $params{StdinDriver} || $stdio_driver;
208 333   33     1265 my $stdout_driver = delete $params{StdoutDriver} || $stdio_driver;
209 333   33     1323 my $stderr_driver = delete $params{StderrDriver} || POE::Driver::SysRW->new();
210              
211 333         540 my $stdio_filter = delete $params{Filter};
212 333         475 my $stdin_filter = delete $params{StdinFilter};
213 333         472 my $stdout_filter = delete $params{StdoutFilter};
214 333         406 my $stderr_filter = delete $params{StderrFilter};
215              
216             #For optional redirection...
217 333         407 my $redir_err = delete $params{RedirectStderr};
218 333         425 my $redir_out = delete $params{RedirectStdout};
219 333         530 my $redir_in = delete $params{RedirectStdin};
220 333         483 my $redir_output = delete $params{RedirectOutput};
221              
222 333         450 my $no_stdin = delete $params{NoStdin};
223              
224 333 100       768 if(defined $redir_output) {
225 3         26 $redir_out = $redir_err = $redir_output;
226             }
227              
228             #Sanity check. We can't wait for redirected filehandles
229 333 100 66     3394 if( (defined $redir_in and defined $stdin_event) ||
      100        
      33        
      66        
      66        
230             (defined $redir_out and defined $stdout_event) ||
231             (defined $redir_err and defined $stderr_event) ) {
232 15         1441 croak("Redirect* and *Event stdio options are mutually exclusive");
233             }
234              
235 318 100       881 if (defined $stdio_filter) {
236 15 50       1596 croak "Filter and StdioFilter cannot be used together"
237             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 303         604 $stdio_filter = delete $params{StdioFilter};
244             }
245 303 100       2339 $stdio_filter = POE::Filter::Line->new(Literal => "\n")
246             unless defined $stdio_filter;
247              
248 303 100       834 $stdin_filter = $stdio_filter unless defined $stdin_filter;
249 303 100       741 $stdout_filter = $stdio_filter unless defined $stdout_filter;
250              
251 303 50 66     1104 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 303 100       1156 $stderr_filter = POE::Filter::Line->new(Literal => "\n")
257             unless defined $stderr_filter;
258             }
259              
260 303 50 66     1856 croak "$type needs either StdioFilter or StdinFilter when using StdinEvent"
261             if defined($stdin_event) and not defined($stdin_filter);
262 303 50 66     1630 croak "$type needs either StdioFilter or StdoutFilter when using StdoutEvent"
263             if defined($stdout_event) and not defined($stdout_filter);
264 303 50 66     1746 croak "$type needs a StderrFilter when using StderrEvent"
265             if defined($stderr_event) and not defined($stderr_filter);
266              
267 303         734 my $error_event = delete $params{ErrorEvent};
268 303         535 my $close_event = delete $params{CloseEvent};
269              
270 303         504 my $no_setsid = delete $params{NoSetSid};
271 303         422 my $no_setpgrp = delete $params{NoSetPgrp};
272              
273             # Make sure the user didn't pass in parameters we're not aware of.
274 303 50       798 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 303 100       942 unless (ref($program) eq 'CODE') {
283 255 50 33     1793 croak "Someone has closed or moved STDIN... exec() won't find it"
284             unless defined fileno(STDIN) && fileno(STDIN) == 0;
285 255 50 33     2123 croak "Someone has closed or moved STDOUT... exec() won't find it"
      33        
286             unless tied(*STDOUT) || defined fileno(STDOUT) && fileno(STDOUT) == 1;
287 255 50 33     1787 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 303         421 $stdin_read, $stdout_write, $stdout_read, $stdin_write,
293             $stderr_read, $stderr_write,
294             );
295              
296 303         1238 _filespec_to_fh(\$stdin_read, "<", $redir_in);
297 303 100       708 if($redir_output) {
298 3         27 _filespec_to_fh(\$stdout_write, ">", $redir_output);
299 3         13 _filespec_to_fh(\$stderr_write, ">", $stdout_write);
300             } else {
301 300         779 _filespec_to_fh(\$stdout_write, ">", $redir_out);
302 300         650 _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 303         5393 my ($sem_pipe_read, $sem_pipe_write) = POE::Pipe::OneWay->new();
309 303 50       27664 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 303 100 66     2011 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 301 100       1777 if ($conduit =~ /^pty(-pipe)?$/) {
    50          
320 22         48 croak "IO::Pty is not available" unless PTY_AVAILABLE;
321              
322 22 50 33     307 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 22         344 $stdin_write = $stdout_read = IO::Pty->new();
327 22 50       13696 croak "could not create master pty: $!" unless defined $stdout_read;
328 22 100       81 if ($conduit eq "pty-pipe") {
329 10         97 ($stderr_read, $stderr_write) = POE::Pipe::OneWay->new();
330 10 50 33     583 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 279         2352 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 837         1532 my ($redir_ref,$rfd_ref,$wfd_ref,$evname, $prettyprint) = @$_;
348 837 100 66     3331 if(defined $evname && (!defined $$redir_ref)) {
349 610         2394 ($$rfd_ref,$$wfd_ref) = POE::Pipe::OneWay->new();
350 610 50 33     27046 croak "could not make $prettyprint pipe: $!"
351             unless defined $$rfd_ref and defined $$wfd_ref;
352             }
353             }
354 279 100 66     2376 unless (defined($redir_in) or $no_stdin) {
355 276         1310 ($stdin_read, $stdin_write) = POE::Pipe::OneWay->new();
356 276 50 33     14218 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 303         515 my $must_unmask;
369 303 50       1985 if( $poe_kernel->can( '_data_sig_mask_all' ) ) {
370 303         1256 $poe_kernel->_data_sig_mask_all;
371 303         526 $must_unmask = 1;
372             }
373              
374             # Fork! Woo-hoo!
375 303         268465 my $pid = fork;
376              
377             # Child. Parent side continues after this block.
378 303 100       8367 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 48 50       2906 __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 48 50       1617 if (tied *STDIN) {
387 0         0 carp "Cannot redirect out of tied STDIN. Untying it";
388 0         0 untie *STDIN;
389             }
390              
391 48 50       1082 if (tied *STDOUT) {
392 0         0 carp "Cannot redirect into tied STDOUT. Untying it";
393 0         0 untie *STDOUT;
394             }
395              
396 48 100       954 if (tied *STDERR) {
397 1         766 carp "Cannot redirect into tied STDERR. Untying it";
398 1         193 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 48 100       1676 if ($conduit =~ /^pty(-pipe)?$/) {
404              
405             # Become a new unix session.
406             # Program 19.3, APITUE. W. Richard Stevens built my hot rod.
407 4 50       1572 eval 'setsid()' unless $no_setsid;
408              
409             # Acquire a controlling terminal. Program 19.3, APITUE.
410 4         104 $stdin_write->make_slave_controlling_terminal();
411              
412             # Open the slave side of the pty.
413 4         2707 $stdin_read = $stdout_write = $stdin_write->slave();
414 4 50       117 __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       63 $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         170 $stdin_read->set_raw();
423              
424 4         2501 if (TIOCSWINSZ_AVAILABLE) {
425 4 50       54 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 44 50       15963 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 48         2361 my @safe_signals = $poe_kernel->_data_sig_get_safe_signals();
445 48         6092 @SIG{@safe_signals} = ("DEFAULT") x @safe_signals;
446 48 50       1259 $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 48 50       369 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 48 50       519 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 48 50       485 if (defined $user_id) {
480 0         0 $< = $> = $user_id;
481             }
482              
483             # Close what the child won't need.
484 48 100       1119 close $stdin_write if defined $stdin_write;
485 48 100       629 close $stdout_read if defined $stdout_read;
486 48 100       498 close $stderr_read if defined $stderr_read;
487              
488 48 50       438 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 48         1996 __PACKAGE__->_redirect_child_stdio_sanely(
496             $stdin_read, $stdout_write, $stderr_write
497             );
498             }
499              
500             # Make STDOUT and/or STDERR auto-flush.
501 48         672 select STDERR; $| = 1;
  48         437  
502 48         8609 select STDOUT; $| = 1;
  48         198  
503              
504             # The child doesn't need to read from the semaphore pipe.
505 48         408 $sem_pipe_read = undef;
506              
507             # Run Perl code. This is fairly consistent across most systems.
508              
509 48 100       1086 if (ref($program) eq 'CODE') {
510              
511             # Tell the parent that the stdio has been set up.
512 1         110 print $sem_pipe_write "go\n";
513 1         15 close $sem_pipe_write;
514              
515             # Close any close-on-exec file descriptors. Except STDIN,
516             # STDOUT, and STDERR, of course.
517 1 50       4 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 1         3 eval { $program->(@$prog_args) };
  1         18  
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       344 $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         5674 print $sem_pipe_write "go\n";
552 47         9813 close $sem_pipe_write;
553              
554             # exec(ARRAY)
555 47 50       7469 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 255 100       6556 defined($stdin_read) and close $stdin_read;
570 255 100       2714 defined($stdout_write) and close $stdout_write;
571 255 100       1685 defined($stderr_write) and close $stderr_write;
572              
573              
574              
575             # Also close any slave ptys
576 255 100 100     8268 $stdout_read->close_slave() if (
577             defined $stdout_read and ref($stdout_read) eq 'IO::Pty'
578             );
579              
580 255 50 66     5018 $stderr_read->close_slave() if (
581             defined $stderr_read and ref($stderr_read) eq 'IO::Pty'
582             );
583              
584 255         734 my $active_count = 0;
585 255 100 66     2832 $active_count++ if $stdout_event and $stdout_read;
586 255 100 66     1597 $active_count++ if $stderr_event and $stderr_read;
587              
588 255         10379 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 255 50       6324 $poe_kernel->_data_sig_unmask_all if $must_unmask;
622              
623             # Wait here while the child sets itself up.
624 255         1288 $sem_pipe_write = undef;
625             {
626 255         6009 local $/ = "\n"; # TODO - Needed?
  255         6636  
627 255         374012 my $chldout = <$sem_pipe_read>;
628 255         1067 chomp $chldout;
629 255 50       2583 $self->[MSWIN32_GROUP_PID] = $chldout if $chldout ne 'go';
630             }
631 255         4657 close $sem_pipe_read;
632              
633 255 100       5201 $self->_define_stdin_flusher() if defined $stdin_write;
634 255 100       37845 $self->_define_stdout_reader() if defined $stdout_read;
635 255 100       2273 $self->_define_stderr_reader() if defined $stderr_read;
636              
637 255         8334 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 251     251   443 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 251         1416 my $unique_id = $self->[UNIQUE_ID];
650 251         467 my $driver = $self->[DRIVER_STDIN];
651 251         470 my $error_event = \$self->[ERROR_EVENT];
652 251         486 my $close_event = \$self->[CLOSE_EVENT];
653 251         413 my $stdin_filter = $self->[FILTER_STDIN];
654 251         434 my $stdin_event = \$self->[EVENT_STDIN];
655 251         441 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 251         537 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   151 0 && CRIMSON_SCOPE_HACK('<');
667             # subroutine starts here
668 146         425 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
669              
670 146         1080 $$stdin_octets = $driver->flush($handle);
671              
672             # When you can't write, nothing else matters.
673 146 50       758 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       300 unless ($$stdin_octets) {
687 146         476 $k->select_pause_write($handle);
688 146 100       812 $$stdin_event && $k->call($me, $$stdin_event, $unique_id);
689             }
690             }
691             }
692 251         10666 );
693              
694 251         3916 $poe_kernel->select_write($self->[HANDLE_STDIN], $self->[STATE_STDIN]);
695              
696             # Pause the write select immediately, unless output is pending.
697 251 50       2940 $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 248     248   421 my $self = shift;
709              
710             # Can't do anything if we don't have a handle.
711 248 50       807 return unless defined $self->[HANDLE_STDOUT];
712              
713             # No event? Unregister the handler and leave.
714 248         636 my $stdout_event = \$self->[EVENT_STDOUT];
715 248 50       735 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 248         578 my $unique_id = $self->[UNIQUE_ID];
723 248         394 my $driver = $self->[DRIVER_STDOUT];
724 248         469 my $stdout_filter = $self->[FILTER_STDOUT];
725              
726             # These can change without redefining the callback since they're
727             # enclosed by reference.
728 248         441 my $is_active = \$self->[IS_ACTIVE];
729 248         404 my $close_event = \$self->[CLOSE_EVENT];
730 248         447 my $error_event = \$self->[ERROR_EVENT];
731              
732             # Register the select-read handler for STDOUT.
733 248 100 66     6047 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 241     241   335 0 && CRIMSON_SCOPE_HACK('<');
742              
743             # subroutine starts here
744 241         7076 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
745 241 100       1498 if (defined(my $raw_input = $driver->get($handle))) {
746 57         5743 $stdout_filter->get_one_start($raw_input);
747 57         80 while (1) {
748 114         338 my $next_rec = $stdout_filter->get_one();
749 114 100       411 last unless @$next_rec;
750 57         115 foreach my $cooked_input (@$next_rec) {
751 57         257 $k->call($me, $$stdout_event, $cooked_input, $unique_id);
752             }
753             }
754             }
755             else {
756 184 100       1109 $$error_event and $k->call(
757             $me, $$error_event,
758             'read', ($!+0), $!, $unique_id, 'STDOUT'
759             );
760 184 100       547 unless (--$$is_active) {
761 137 100       677 $k->call( $me, $$close_event, $unique_id )
762             if defined $$close_event;
763             }
764 184         807 $k->select_read($handle);
765             }
766             }
767 217         3931 );
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 28     28   43 0 && CRIMSON_SCOPE_HACK('<');
777              
778             # subroutine starts here
779 28         92 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
780 28 100       230 if (defined(my $raw_input = $driver->get($handle))) {
781 18         28 foreach my $cooked_input (@{$stdout_filter->get($raw_input)}) {
  18         104  
782 16         65 $k->call($me, $$stdout_event, $cooked_input, $unique_id);
783             }
784             }
785             else {
786 10 50       97 $$error_event and
787             $k->call(
788             $me, $$error_event,
789             'read', ($!+0), $!, $unique_id, 'STDOUT'
790             );
791 10 100       37 unless (--$$is_active) {
792 5 50       33 $k->call( $me, $$close_event, $unique_id )
793             if defined $$close_event;
794             }
795 10         45 $k->select_read($handle);
796             }
797             }
798 31         708 );
799             }
800              
801             # register the state's select
802 248         1262 $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 166     166   399 my $self = shift;
811              
812             # Can't do anything if we don't have a handle.
813 166 50       574 return unless defined $self->[HANDLE_STDERR];
814              
815             # No event? Unregister the handler and leave.
816 166         496 my $stderr_event = \$self->[EVENT_STDERR];
817 166 50       494 unless ($$stderr_event) {
818 0         0 $poe_kernel->select_read($self->[HANDLE_STDERR]);
819 0         0 return;
820             }
821              
822 166         432 my $unique_id = $self->[UNIQUE_ID];
823 166         306 my $driver = $self->[DRIVER_STDERR];
824 166         311 my $stderr_filter = $self->[FILTER_STDERR];
825              
826             # These can change without redefining the callback since they're
827             # enclosed by reference.
828 166         342 my $error_event = \$self->[ERROR_EVENT];
829 166         425 my $close_event = \$self->[CLOSE_EVENT];
830 166         324 my $is_active = \$self->[IS_ACTIVE];
831              
832             # Register the select-read handler for STDERR.
833 166 100 66     2213 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 213     213   357 0 && CRIMSON_SCOPE_HACK('<');
842              
843             # subroutine starts here
844 213         755 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
845 213 100       1204 if (defined(my $raw_input = $driver->get($handle))) {
846 104         744 $stderr_filter->get_one_start($raw_input);
847 104         180 while (1) {
848 202         639 my $next_rec = $stderr_filter->get_one();
849 202 100       905 last unless @$next_rec;
850 98         281 foreach my $cooked_input (@$next_rec) {
851 98         656 $k->call($me, $$stderr_event, $cooked_input, $unique_id);
852             }
853             }
854             }
855             else {
856 109 100       1209 $$error_event and $k->call(
857             $me, $$error_event,
858             'read', ($!+0), $!, $unique_id, 'STDERR'
859             );
860 109 100       485 unless (--$$is_active) {
861 47 50       287 $k->call( $me, $$close_event, $unique_id )
862             if defined $$close_event;
863             }
864 109         484 $k->select_read($handle);
865             }
866             }
867 143         2269 );
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 14     14   22 0 && CRIMSON_SCOPE_HACK('<');
877              
878             # subroutine starts here
879 14         48 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
880 14 100       72 if (defined(my $raw_input = $driver->get($handle))) {
881 8         14 foreach my $cooked_input (@{$stderr_filter->get($raw_input)}) {
  8         45  
882 4         21 $k->call($me, $$stderr_event, $cooked_input, $unique_id);
883             }
884             }
885             else {
886 6 50       51 $$error_event and $k->call(
887             $me, $$error_event,
888             'read', ($!+0), $!, $unique_id, 'STDERR'
889             );
890 6 100       24 unless (--$$is_active) {
891 5 50       26 $k->call( $me, $$close_event, $unique_id )
892             if defined $$close_event;
893             }
894 6         27 $k->select_read($handle);
895             }
896             }
897 23         683 );
898             }
899              
900             # Register the state's select.
901 166         601 $poe_kernel->select_read($self->[HANDLE_STDERR], $self->[STATE_STDERR]);
902             }
903              
904             #------------------------------------------------------------------------------
905             # Redefine events.
906              
907             sub event {
908 142     142 1 2019 my $self = shift;
909 142 50       392 push(@_, undef) if (scalar(@_) & 1);
910              
911 142         267 my ($redefine_stdin, $redefine_stdout, $redefine_stderr) = (0, 0, 0);
912              
913 142         473 while (@_) {
914 347         687 my ($name, $event) = splice(@_, 0, 2);
915              
916 347 100       1043 if ($name eq 'StdinEvent') {
    100          
    100          
    100          
    50          
917 71         130 $self->[EVENT_STDIN] = $event;
918 71         252 $redefine_stdin = 1;
919             }
920             elsif ($name eq 'StdoutEvent') {
921 71         137 $self->[EVENT_STDOUT] = $event;
922 71         154 $redefine_stdout = 1;
923             }
924             elsif ($name eq 'StderrEvent') {
925 63 50       139 if ($self->[CONDUIT_TYPE] ne 'pty') {
926 63         87 $self->[EVENT_STDERR] = $event;
927 63         127 $redefine_stderr = 1;
928             }
929             else {
930 0         0 carp "ignoring StderrEvent on a pty conduit";
931             }
932             }
933             elsif ($name eq 'ErrorEvent') {
934 71         176 $self->[ERROR_EVENT] = $event;
935             }
936             elsif ($name eq 'CloseEvent') {
937 71         155 $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 142         155 my $active_count = 0;
946 142 50 33     1212 $active_count++ if $self->[EVENT_STDOUT] and $self->[HANDLE_STDOUT];
947 142 100 66     562 $active_count++ if $self->[EVENT_STDERR] and $self->[HANDLE_STDERR];
948 142         275 $self->[IS_ACTIVE] = $active_count;
949             }
950              
951             #------------------------------------------------------------------------------
952             # Destroy the wheel.
953              
954             sub DESTROY {
955 203     203   7218 my $self = shift;
956              
957 203 100       1135 return if(ref POE::Kernel->get_active_session eq 'POE::Kernel');
958              
959             # Turn off the STDIN thing.
960 201 100       673 if ($self->[HANDLE_STDIN]) {
961 197         1035 $poe_kernel->select_write($self->[HANDLE_STDIN]);
962 197         359 $self->[HANDLE_STDIN] = undef;
963             }
964              
965 201 100       4209 if ($self->[STATE_STDIN]) {
966 199         922 $poe_kernel->state($self->[STATE_STDIN]);
967 199         426 $self->[STATE_STDIN] = undef;
968             }
969              
970 201 100       1061 if ($self->[HANDLE_STDOUT]) {
971 196         666 $poe_kernel->select_read($self->[HANDLE_STDOUT]);
972 196         333 $self->[HANDLE_STDOUT] = undef;
973             }
974 201 100       2107 if ($self->[STATE_STDOUT]) {
975 196         678 $poe_kernel->state($self->[STATE_STDOUT]);
976 196         388 $self->[STATE_STDOUT] = undef;
977             }
978              
979 201 100       573 if ($self->[HANDLE_STDERR]) {
980 118         428 $poe_kernel->select_read($self->[HANDLE_STDERR]);
981 118         242 $self->[HANDLE_STDERR] = undef;
982             }
983 201 100       1268 if ($self->[STATE_STDERR]) {
984 118         422 $poe_kernel->state($self->[STATE_STDERR]);
985 118         271 $self->[STATE_STDERR] = undef;
986             }
987              
988 201         968 &POE::Wheel::free_wheel_id($self->[UNIQUE_ID]);
989             }
990              
991             #------------------------------------------------------------------------------
992             # Queue input for the child process.
993              
994             sub put {
995 212     212 1 6616 my ($self, @chunks) = @_;
996              
997             # Avoid big bada boom if someone put()s on a dead wheel.
998 212 100       1042 croak "Called put() on a wheel without an open STDIN handle" unless (
999             $self->[HANDLE_STDIN]
1000             );
1001              
1002 210 50       2943 if (
1003             $self->[OCTETS_STDIN] = # assignment on purpose
1004             $self->[DRIVER_STDIN]->put($self->[FILTER_STDIN]->put(\@chunks))
1005             ) {
1006 210         960 $poe_kernel->select_resume_write($self->[HANDLE_STDIN]);
1007             }
1008              
1009             # No watermark.
1010 210         728 return 0;
1011             }
1012              
1013             #------------------------------------------------------------------------------
1014             # Pause and resume various input events.
1015              
1016             sub pause_stdout {
1017 2     2 1 2538 my $self = shift;
1018 2 50       11 return unless defined $self->[HANDLE_STDOUT];
1019 2         24 $poe_kernel->select_pause_read($self->[HANDLE_STDOUT]);
1020             }
1021              
1022             sub pause_stderr {
1023 2     2 1 3206 my $self = shift;
1024 2 50       10 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 296 my $self = shift;
1030 2 50       10 return unless defined $self->[HANDLE_STDOUT];
1031 2         12 $poe_kernel->select_resume_read($self->[HANDLE_STDOUT]);
1032             }
1033              
1034             sub resume_stderr {
1035 2     2 1 2211 my $self = shift;
1036 2 50       10 return unless defined $self->[HANDLE_STDERR];
1037 2         10 $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 2161 my $self = shift;
1043 2 50       12 return unless defined $self->[HANDLE_STDIN];
1044              
1045 2         11 $poe_kernel->select_write($self->[HANDLE_STDIN], undef);
1046              
1047 2         4 eval { local $^W = 0; shutdown($self->[HANDLE_STDIN], 1) };
  2         23  
  2         31  
1048 2 50 33     27 if ($@ or $self->[HANDLE_STDIN] != $self->[HANDLE_STDOUT]) {
1049 2         9 close $self->[HANDLE_STDIN];
1050             }
1051              
1052 2         6 $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 10460 $_[0]->[OCTETS_STDIN];
1194             }
1195              
1196             sub get_driver_out_messages {
1197 20     20 1 103 $_[0]->[DRIVER_STDIN]->get_out_messages_buffered();
1198             }
1199              
1200             sub ID {
1201 170     170 1 3025 $_[0]->[UNIQUE_ID];
1202             }
1203              
1204             sub PID {
1205 300     300 1 20079 $_[0]->[CHILD_PID];
1206             }
1207              
1208             sub kill {
1209 4     4 1 4452 my ($self, $signal) = @_;
1210 4 50       43 $signal = 'TERM' unless defined $signal;
1211 4 50       15 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         137  
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 909     909   1380 my ($dest,$mode,$fspec) = @_;
1270 909 100       1678 return unless defined $fspec;
1271 9 50       26 if(ref $fspec) {
1272 9 50       29 if (ref $fspec eq 'GLOB') {
1273 9         149 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 48     48   401 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 48 50       462 if(defined $stdin_read) {
1290 48 50       2779 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 48 100       411 if(defined $stdout_write) {
1297 47 50       10195 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 48 100       393 if(defined $stderr_write) {
1303 32 50       631 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 0 0 0       $cmdline = join(
1366             ' ',
1367 0           map { /\s/ && ! /"/ ? qq{"$_"} : $_ }
1368             (@$program, @$prog_args)
1369             );
1370             }
1371             else {
1372 0           $appname = undef;
1373 0 0 0       $cmdline = join(
1374             ' ', $program,
1375 0           map { /\s/ && ! /"/ ? qq{"$_"} : $_ }
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__