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 71     71   21765 use strict;
  71         88  
  71         2959  
4              
5 71     71   352 use vars qw($VERSION @ISA);
  71         123  
  71         4207  
6             $VERSION = '1.365'; # NOTE - Should be #.### (three decimal places)
7              
8 71     71   341 use Carp qw(carp croak);
  71         93  
  71         4276  
9 71         556 use POSIX qw(
10             sysconf setsid _SC_OPEN_MAX ECHO ICANON IEXTEN ISIG BRKINT ICRNL
11             INPCK ISTRIP IXON CSIZE PARENB OPOST TCSANOW
12 71     71   318 );
  71         87  
13              
14 71     71   9419 use POE qw( Wheel Pipe::TwoWay Pipe::OneWay Driver::SysRW Filter::Line );
  71         155  
  71         740  
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 71 50   71   406 die "$^O does not support fork()\n" if $^O eq 'MacOS';
25              
26 71         380 local $SIG{'__DIE__'} = 'DEFAULT';
27 71         167 eval { require IO::Pty; };
  71         39286  
28 71 50       386082 if ($@) {
29 0         0 eval '
30             sub PTY_AVAILABLE () { 0 }
31             sub TIOCSWINSZ_AVAILABLE () { 0 }
32             ';
33             }
34             else {
35 71         1784 IO::Pty->import();
36 71         3049 eval 'sub PTY_AVAILABLE () { 1 }';
37              
38 71         199 eval { require IO::Tty; };
  71         466  
39 71 50       267 if ($@) {
40 0         0 eval 'sub TIOCSWINSZ_AVAILABLE () { 0 }';
41             }
42             else {
43 71         321 IO::Tty->import('TIOCSWINSZ');
44 71         7089 eval 'sub TIOCSWINSZ_AVAILABLE () { 1 }';
45             }
46             }
47              
48 71 50       451 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 71         148 my $max_open_fds;
74 71         121 eval {
75 71         466 $max_open_fds = sysconf(_SC_OPEN_MAX);
76             };
77 71 50       274 $max_open_fds = 1024 unless $max_open_fds;
78 71         2560 eval "sub MAX_OPEN_FDS () { $max_open_fds }";
79 71 50       478033 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 345     345 1 7898 my $type = shift;
121 345 50       1041 croak "$type needs an even number of parameters" if @_ & 1;
122 345         2847 my %params = @_;
123              
124 345 50 33     2313 croak "wheels no longer require a kernel reference as their first parameter"
125             if @_ and ref($_[0]) eq 'POE::Kernel';
126              
127 345 50       945 croak "$type requires a working Kernel" unless defined $poe_kernel;
128              
129 345         958 my $program = delete $params{Program};
130 345 100       2752 croak "$type needs a Program parameter" unless defined $program;
131              
132 331         625 my $prog_args = delete $params{ProgramArgs};
133 331 100       1264 $prog_args = [] unless defined $prog_args;
134 331 50       1056 croak "ProgramArgs must be an ARRAY reference"
135             unless ref($prog_args) eq "ARRAY";
136              
137 331         613 my $priority_delta = delete $params{Priority};
138 331 50       1008 $priority_delta = 0 unless defined $priority_delta;
139              
140 331         503 my $close_on_call = delete $params{CloseOnCall};
141 331 50       1027 $close_on_call = 0 unless defined $close_on_call;
142              
143 331         418 my $user_id = delete $params{User};
144 331         467 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 331         490 my $conduit = delete $params{Conduit};
157 331         786 my $stdio_type;
158 331 100       18984 if (defined $conduit) {
159 56 100 100     2276 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 42 100       447 unless ($conduit =~ /^pty(-pipe)?$/) {
167 24         43 $stdio_type = $conduit;
168 24         135 $conduit = "pipe";
169             }
170             }
171             else {
172 275         566 $conduit = "pipe";
173             }
174              
175 317         601 my $winsize = delete $params{Winsize};
176              
177 317 50       778 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 317         654 my $stdin_event = delete $params{StdinEvent};
195 317         604 my $stdout_event = delete $params{StdoutEvent};
196 317         612 my $stderr_event = delete $params{StderrEvent};
197              
198 317 50 66     1257 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 317   33     3784 my $stdio_driver = delete $params{StdioDriver} || POE::Driver::SysRW->new();
207 317   33     1539 my $stdin_driver = delete $params{StdinDriver} || $stdio_driver;
208 317   33     1233 my $stdout_driver = delete $params{StdoutDriver} || $stdio_driver;
209 317   33     1540 my $stderr_driver = delete $params{StderrDriver} || POE::Driver::SysRW->new();
210              
211 317         528 my $stdio_filter = delete $params{Filter};
212 317         564 my $stdin_filter = delete $params{StdinFilter};
213 317         526 my $stdout_filter = delete $params{StdoutFilter};
214 317         486 my $stderr_filter = delete $params{StderrFilter};
215              
216             #For optional redirection...
217 317         420 my $redir_err = delete $params{RedirectStderr};
218 317         485 my $redir_out = delete $params{RedirectStdout};
219 317         520 my $redir_in = delete $params{RedirectStdin};
220 317         460 my $redir_output = delete $params{RedirectOutput};
221              
222 317         447 my $no_stdin = delete $params{NoStdin};
223              
224 317 100       738 if(defined $redir_output) {
225 2         12 $redir_out = $redir_err = $redir_output;
226             }
227              
228             #Sanity check. We can't wait for redirected filehandles
229 317 100 66     3788 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 14         1584 croak("Redirect* and *Event stdio options are mutually exclusive");
233             }
234              
235 303 100       928 if (defined $stdio_filter) {
236 14 50       1768 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 289         569 $stdio_filter = delete $params{StdioFilter};
244             }
245 289 100       2087 $stdio_filter = POE::Filter::Line->new(Literal => "\n")
246             unless defined $stdio_filter;
247              
248 289 100       850 $stdin_filter = $stdio_filter unless defined $stdin_filter;
249 289 100       766 $stdout_filter = $stdio_filter unless defined $stdout_filter;
250              
251 289 50 66     1206 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 289 100       1261 $stderr_filter = POE::Filter::Line->new(Literal => "\n")
257             unless defined $stderr_filter;
258             }
259              
260 289 50 66     1596 croak "$type needs either StdioFilter or StdinFilter when using StdinEvent"
261             if defined($stdin_event) and not defined($stdin_filter);
262 289 50 66     1706 croak "$type needs either StdioFilter or StdoutFilter when using StdoutEvent"
263             if defined($stdout_event) and not defined($stdout_filter);
264 289 50 66     1652 croak "$type needs a StderrFilter when using StderrEvent"
265             if defined($stderr_event) and not defined($stderr_filter);
266              
267 289         653 my $error_event = delete $params{ErrorEvent};
268 289         527 my $close_event = delete $params{CloseEvent};
269              
270 289         431 my $no_setsid = delete $params{NoSetSid};
271 289         419 my $no_setpgrp = delete $params{NoSetPgrp};
272              
273             # Make sure the user didn't pass in parameters we're not aware of.
274 289 50       1163 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 289 100       980 unless (ref($program) eq 'CODE') {
283 249 50 33     1898 croak "Someone has closed or moved STDIN... exec() won't find it"
284             unless defined fileno(STDIN) && fileno(STDIN) == 0;
285 249 50 33     2273 croak "Someone has closed or moved STDOUT... exec() won't find it"
      33        
286             unless tied(*STDOUT) || defined fileno(STDOUT) && fileno(STDOUT) == 1;
287 249 50 33     2190 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 289         397 $stdin_read, $stdout_write, $stdout_read, $stdin_write,
293             $stderr_read, $stderr_write,
294             );
295              
296 289         1337 _filespec_to_fh(\$stdin_read, "<", $redir_in);
297 289 100       681 if($redir_output) {
298 2         18 _filespec_to_fh(\$stdout_write, ">", $redir_output);
299 2         6 _filespec_to_fh(\$stderr_write, ">", $stdout_write);
300             } else {
301 287         954 _filespec_to_fh(\$stdout_write, ">", $redir_out);
302 287         598 _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 289         4325 my ($sem_pipe_read, $sem_pipe_write) = POE::Pipe::OneWay->new();
309 289 50       26543 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 289 100 66     1619 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 288 100       1777 if ($conduit =~ /^pty(-pipe)?$/) {
    50          
320 18         43 croak "IO::Pty is not available" unless PTY_AVAILABLE;
321              
322 18 50 33     244 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 18         353 $stdin_write = $stdout_read = IO::Pty->new();
327 18 50       12739 croak "could not create master pty: $!" unless defined $stdout_read;
328 18 100       69 if ($conduit eq "pty-pipe") {
329 8         54 ($stderr_read, $stderr_write) = POE::Pipe::OneWay->new();
330 8 50 33     435 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 270         2415 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 810         1568 my ($redir_ref,$rfd_ref,$wfd_ref,$evname, $prettyprint) = @$_;
348 810 100 66     3673 if(defined $evname && (!defined $$redir_ref)) {
349 589         2492 ($$rfd_ref,$$wfd_ref) = POE::Pipe::OneWay->new();
350 589 50 33     28639 croak "could not make $prettyprint pipe: $!"
351             unless defined $$rfd_ref and defined $$wfd_ref;
352             }
353             }
354 270 100 66     2798 unless (defined($redir_in) or $no_stdin) {
355 268         1365 ($stdin_read, $stdin_write) = POE::Pipe::OneWay->new();
356 268 50 33     14392 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 289         465 my $must_unmask;
369 289 50       1938 if( $poe_kernel->can( '_data_sig_mask_all' ) ) {
370 289         1469 $poe_kernel->_data_sig_mask_all;
371 289         654 $must_unmask = 1;
372             }
373              
374             # Fork! Woo-hoo!
375 289         292486 my $pid = fork;
376              
377             # Child. Parent side continues after this block.
378 289 100       8416 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       3002 __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       1929 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       1025 if (tied *STDOUT) {
392 0         0 carp "Cannot redirect into tied STDOUT. Untying it";
393 0         0 untie *STDOUT;
394             }
395              
396 48 100       1348 if (tied *STDERR) {
397 1         1003 carp "Cannot redirect into tied STDERR. Untying it";
398 1         303 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       1836 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       1453 eval 'setsid()' unless $no_setsid;
408              
409             # Acquire a controlling terminal. Program 19.3, APITUE.
410 4         106 $stdin_write->make_slave_controlling_terminal();
411              
412             # Open the slave side of the pty.
413 4         2554 $stdin_read = $stdout_write = $stdin_write->slave();
414 4 50       131 __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       68 $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         86 $stdin_read->set_raw();
423              
424 4         2415 if (TIOCSWINSZ_AVAILABLE) {
425 4 50       46 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       17253 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         1888 my @safe_signals = $poe_kernel->_data_sig_get_safe_signals();
445 48         6190 @SIG{@safe_signals} = ("DEFAULT") x @safe_signals;
446 48 50       1197 $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       382 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       546 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       642 if (defined $user_id) {
480 0         0 $< = $> = $user_id;
481             }
482              
483             # Close what the child won't need.
484 48 100       1187 close $stdin_write if defined $stdin_write;
485 48 100       748 close $stdout_read if defined $stdout_read;
486 48 100       549 close $stderr_read if defined $stderr_read;
487              
488 48 50       449 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         1981 __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         592 select STDERR; $| = 1;
  48         555  
502 48         410 select STDOUT; $| = 1;
  48         7188  
503              
504             # The child doesn't need to read from the semaphore pipe.
505 48         316 $sem_pipe_read = undef;
506              
507             # Run Perl code. This is fairly consistent across most systems.
508              
509 48 100       1397 if (ref($program) eq 'CODE') {
510              
511             # Tell the parent that the stdio has been set up.
512 1         8118 print $sem_pipe_write "go\n";
513 1         20 close $sem_pipe_write;
514              
515             # Close any close-on-exec file descriptors. Except STDIN,
516             # STDOUT, and STDERR, of course.
517 1 50       17 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         11 eval { $program->(@$prog_args) };
  1         11  
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       268 $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         41799 print $sem_pipe_write "go\n";
552 47         983 close $sem_pipe_write;
553              
554             # exec(ARRAY)
555 47 50       7626 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 241 100       6325 defined($stdin_read) and close $stdin_read;
570 241 100       2957 defined($stdout_write) and close $stdout_write;
571 241 100       1808 defined($stderr_write) and close $stderr_write;
572              
573              
574              
575             # Also close any slave ptys
576 241 100 100     7479 $stdout_read->close_slave() if (
577             defined $stdout_read and ref($stdout_read) eq 'IO::Pty'
578             );
579              
580 241 50 66     5078 $stderr_read->close_slave() if (
581             defined $stderr_read and ref($stderr_read) eq 'IO::Pty'
582             );
583              
584 241         586 my $active_count = 0;
585 241 100 66     3424 $active_count++ if $stdout_event and $stdout_read;
586 241 100 66     2191 $active_count++ if $stderr_event and $stderr_read;
587              
588 241         9999 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 241 50       6235 $poe_kernel->_data_sig_unmask_all if $must_unmask;
622              
623             # Wait here while the child sets itself up.
624 241         1275 $sem_pipe_write = undef;
625             {
626 241         6488 local $/ = "\n"; # TODO - Needed?
  241         6851  
627 241         410772 my $chldout = <$sem_pipe_read>;
628 241         1007 chomp $chldout;
629 241 50       4230 $self->[MSWIN32_GROUP_PID] = $chldout if $chldout ne 'go';
630             }
631 241         3083 close $sem_pipe_read;
632              
633 241 100       4648 $self->_define_stdin_flusher() if defined $stdin_write;
634 241 100       2349 $self->_define_stdout_reader() if defined $stdout_read;
635 241 100       2198 $self->_define_stderr_reader() if defined $stderr_read;
636              
637 241         8699 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 239     239   520 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 239         2294 my $unique_id = $self->[UNIQUE_ID];
650 239         489 my $driver = $self->[DRIVER_STDIN];
651 239         503 my $error_event = \$self->[ERROR_EVENT];
652 239         466 my $close_event = \$self->[CLOSE_EVENT];
653 239         399 my $stdin_filter = $self->[FILTER_STDIN];
654 239         403 my $stdin_event = \$self->[EVENT_STDIN];
655 239         565 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 239         628 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 113     113   187 0 && CRIMSON_SCOPE_HACK('<');
667             # subroutine starts here
668 113         290 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
669              
670 113         766 $$stdin_octets = $driver->flush($handle);
671              
672             # When you can't write, nothing else matters.
673 113 50       369 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 113 50       226 unless ($$stdin_octets) {
687 113         397 $k->select_pause_write($handle);
688 113 100       569 $$stdin_event && $k->call($me, $$stdin_event, $unique_id);
689             }
690             }
691             }
692 239         9898 );
693              
694 239         3309 $poe_kernel->select_write($self->[HANDLE_STDIN], $self->[STATE_STDIN]);
695              
696             # Pause the write select immediately, unless output is pending.
697 239 50       2516 $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 237     237   29703 my $self = shift;
709              
710             # Can't do anything if we don't have a handle.
711 237 50       961 return unless defined $self->[HANDLE_STDOUT];
712              
713             # No event? Unregister the handler and leave.
714 237         629 my $stdout_event = \$self->[EVENT_STDOUT];
715 237 50       872 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 237         586 my $unique_id = $self->[UNIQUE_ID];
723 237         417 my $driver = $self->[DRIVER_STDOUT];
724 237         350 my $stdout_filter = $self->[FILTER_STDOUT];
725              
726             # These can change without redefining the callback since they're
727             # enclosed by reference.
728 237         513 my $is_active = \$self->[IS_ACTIVE];
729 237         388 my $close_event = \$self->[CLOSE_EVENT];
730 237         439 my $error_event = \$self->[ERROR_EVENT];
731              
732             # Register the select-read handler for STDOUT.
733 237 100 66     5856 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 225     225   309 0 && CRIMSON_SCOPE_HACK('<');
742              
743             # subroutine starts here
744 225         715 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
745 225 100       1867 if (defined(my $raw_input = $driver->get($handle))) {
746 47         5298 $stdout_filter->get_one_start($raw_input);
747 47         57 while (1) {
748 94         288 my $next_rec = $stdout_filter->get_one();
749 94 100       333 last unless @$next_rec;
750 47         89 foreach my $cooked_input (@$next_rec) {
751 47         1031 $k->call($me, $$stdout_event, $cooked_input, $unique_id);
752             }
753             }
754             }
755             else {
756 178 100       1063 $$error_event and $k->call(
757             $me, $$error_event,
758             'read', ($!+0), $!, $unique_id, 'STDOUT'
759             );
760 178 100       596 unless (--$$is_active) {
761 104 100       813 $k->call( $me, $$close_event, $unique_id )
762             if defined $$close_event;
763             }
764 178         803 $k->select_read($handle);
765             }
766             }
767 211         3884 );
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 14     14   25 0 && CRIMSON_SCOPE_HACK('<');
777              
778             # subroutine starts here
779 14         45 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
780 14 100       69 if (defined(my $raw_input = $driver->get($handle))) {
781 9         10 foreach my $cooked_input (@{$stdout_filter->get($raw_input)}) {
  9         54  
782 8         44 $k->call($me, $$stdout_event, $cooked_input, $unique_id);
783             }
784             }
785             else {
786 5 50       48 $$error_event and
787             $k->call(
788             $me, $$error_event,
789             'read', ($!+0), $!, $unique_id, 'STDOUT'
790             );
791 5 100       21 unless (--$$is_active) {
792 2 50       87 $k->call( $me, $$close_event, $unique_id )
793             if defined $$close_event;
794             }
795 5         24 $k->select_read($handle);
796             }
797             }
798 26         664 );
799             }
800              
801             # register the state's select
802 237         1812 $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 157     157   362 my $self = shift;
811              
812             # Can't do anything if we don't have a handle.
813 157 50       472 return unless defined $self->[HANDLE_STDERR];
814              
815             # No event? Unregister the handler and leave.
816 157         370 my $stderr_event = \$self->[EVENT_STDERR];
817 157 50       422 unless ($$stderr_event) {
818 0         0 $poe_kernel->select_read($self->[HANDLE_STDERR]);
819 0         0 return;
820             }
821              
822 157         367 my $unique_id = $self->[UNIQUE_ID];
823 157         293 my $driver = $self->[DRIVER_STDERR];
824 157         269 my $stderr_filter = $self->[FILTER_STDERR];
825              
826             # These can change without redefining the callback since they're
827             # enclosed by reference.
828 157         277 my $error_event = \$self->[ERROR_EVENT];
829 157         291 my $close_event = \$self->[CLOSE_EVENT];
830 157         260 my $is_active = \$self->[IS_ACTIVE];
831              
832             # Register the select-read handler for STDERR.
833 157 100 66     2931 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 196     196   304 0 && CRIMSON_SCOPE_HACK('<');
842              
843             # subroutine starts here
844 196         1198 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
845 196 100       1268 if (defined(my $raw_input = $driver->get($handle))) {
846 93         592 $stderr_filter->get_one_start($raw_input);
847 93         135 while (1) {
848 183         554 my $next_rec = $stderr_filter->get_one();
849 183 100       654 last unless @$next_rec;
850 90         243 foreach my $cooked_input (@$next_rec) {
851 90         573 $k->call($me, $$stderr_event, $cooked_input, $unique_id);
852             }
853             }
854             }
855             else {
856 103 100       767 $$error_event and $k->call(
857             $me, $$error_event,
858             'read', ($!+0), $!, $unique_id, 'STDERR'
859             );
860 103 100       386 unless (--$$is_active) {
861 74 100       373 $k->call( $me, $$close_event, $unique_id )
862             if defined $$close_event;
863             }
864 103         363 $k->select_read($handle);
865             }
866             }
867 137         2107 );
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 7     7   13 0 && CRIMSON_SCOPE_HACK('<');
877              
878             # subroutine starts here
879 7         21 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
880 7 100       31 if (defined(my $raw_input = $driver->get($handle))) {
881 4         7 foreach my $cooked_input (@{$stderr_filter->get($raw_input)}) {
  4         21  
882 2         10 $k->call($me, $$stderr_event, $cooked_input, $unique_id);
883             }
884             }
885             else {
886 3 50       28 $$error_event and $k->call(
887             $me, $$error_event,
888             'read', ($!+0), $!, $unique_id, 'STDERR'
889             );
890 3 50       12 unless (--$$is_active) {
891 3 50       18 $k->call( $me, $$close_event, $unique_id )
892             if defined $$close_event;
893             }
894 3         11 $k->select_read($handle);
895             }
896             }
897 20         401 );
898             }
899              
900             # Register the state's select.
901 157         604 $poe_kernel->select_read($self->[HANDLE_STDERR], $self->[STATE_STDERR]);
902             }
903              
904             #------------------------------------------------------------------------------
905             # Redefine events.
906              
907             sub event {
908 120     120 1 1472 my $self = shift;
909 120 50       366 push(@_, undef) if (scalar(@_) & 1);
910              
911 120         271 my ($redefine_stdin, $redefine_stdout, $redefine_stderr) = (0, 0, 0);
912              
913 120         270 while (@_) {
914 294         669 my ($name, $event) = splice(@_, 0, 2);
915              
916 294 100       937 if ($name eq 'StdinEvent') {
    100          
    100          
    100          
    50          
917 60         100 $self->[EVENT_STDIN] = $event;
918 60         160 $redefine_stdin = 1;
919             }
920             elsif ($name eq 'StdoutEvent') {
921 60         271 $self->[EVENT_STDOUT] = $event;
922 60         162 $redefine_stdout = 1;
923             }
924             elsif ($name eq 'StderrEvent') {
925 54 50       159 if ($self->[CONDUIT_TYPE] ne 'pty') {
926 54         82 $self->[EVENT_STDERR] = $event;
927 54         134 $redefine_stderr = 1;
928             }
929             else {
930 0         0 carp "ignoring StderrEvent on a pty conduit";
931             }
932             }
933             elsif ($name eq 'ErrorEvent') {
934 60         162 $self->[ERROR_EVENT] = $event;
935             }
936             elsif ($name eq 'CloseEvent') {
937 60         146 $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 120         429 my $active_count = 0;
946 120 50 33     932 $active_count++ if $self->[EVENT_STDOUT] and $self->[HANDLE_STDOUT];
947 120 100 66     764 $active_count++ if $self->[EVENT_STDERR] and $self->[HANDLE_STDERR];
948 120         323 $self->[IS_ACTIVE] = $active_count;
949             }
950              
951             #------------------------------------------------------------------------------
952             # Destroy the wheel.
953              
954             sub DESTROY {
955 189     189   6082 my $self = shift;
956              
957 189 100       1031 return if(ref POE::Kernel->get_active_session eq 'POE::Kernel');
958              
959             # Turn off the STDIN thing.
960 188 100       707 if ($self->[HANDLE_STDIN]) {
961 186         862 $poe_kernel->select_write($self->[HANDLE_STDIN]);
962 186         413 $self->[HANDLE_STDIN] = undef;
963             }
964              
965 188 100       3792 if ($self->[STATE_STDIN]) {
966 187         934 $poe_kernel->state($self->[STATE_STDIN]);
967 187         468 $self->[STATE_STDIN] = undef;
968             }
969              
970 188 100       619 if ($self->[HANDLE_STDOUT]) {
971 185         677 $poe_kernel->select_read($self->[HANDLE_STDOUT]);
972 185         364 $self->[HANDLE_STDOUT] = undef;
973             }
974 188 100       2017 if ($self->[STATE_STDOUT]) {
975 185         698 $poe_kernel->state($self->[STATE_STDOUT]);
976 185         390 $self->[STATE_STDOUT] = undef;
977             }
978              
979 188 100       630 if ($self->[HANDLE_STDERR]) {
980 109         373 $poe_kernel->select_read($self->[HANDLE_STDERR]);
981 109         261 $self->[HANDLE_STDERR] = undef;
982             }
983 188 100       1084 if ($self->[STATE_STDERR]) {
984 109         414 $poe_kernel->state($self->[STATE_STDERR]);
985 109         211 $self->[STATE_STDERR] = undef;
986             }
987              
988 188         1011 &POE::Wheel::free_wheel_id($self->[UNIQUE_ID]);
989             }
990              
991             #------------------------------------------------------------------------------
992             # Queue input for the child process.
993              
994             sub put {
995 175     175 1 5777 my ($self, @chunks) = @_;
996              
997             # Avoid big bada boom if someone put()s on a dead wheel.
998 175 100       795 croak "Called put() on a wheel without an open STDIN handle" unless (
999             $self->[HANDLE_STDIN]
1000             );
1001              
1002 174 50       2958 if (
1003             $self->[OCTETS_STDIN] = # assignment on purpose
1004             $self->[DRIVER_STDIN]->put($self->[FILTER_STDIN]->put(\@chunks))
1005             ) {
1006 174         831 $poe_kernel->select_resume_write($self->[HANDLE_STDIN]);
1007             }
1008              
1009             # No watermark.
1010 174         573 return 0;
1011             }
1012              
1013             #------------------------------------------------------------------------------
1014             # Pause and resume various input events.
1015              
1016             sub pause_stdout {
1017 1     1 1 1855 my $self = shift;
1018 1 50       7 return unless defined $self->[HANDLE_STDOUT];
1019 1         7 $poe_kernel->select_pause_read($self->[HANDLE_STDOUT]);
1020             }
1021              
1022             sub pause_stderr {
1023 1     1 1 3516 my $self = shift;
1024 1 50       5 return unless defined $self->[HANDLE_STDERR];
1025 1         8 $poe_kernel->select_pause_read($self->[HANDLE_STDERR]);
1026             }
1027              
1028             sub resume_stdout {
1029 1     1 1 185 my $self = shift;
1030 1 50       5 return unless defined $self->[HANDLE_STDOUT];
1031 1         12 $poe_kernel->select_resume_read($self->[HANDLE_STDOUT]);
1032             }
1033              
1034             sub resume_stderr {
1035 1     1 1 1212 my $self = shift;
1036 1 50       4 return unless defined $self->[HANDLE_STDERR];
1037 1         6 $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 1     1 1 2878 my $self = shift;
1043 1 50       6 return unless defined $self->[HANDLE_STDIN];
1044              
1045 1         9 $poe_kernel->select_write($self->[HANDLE_STDIN], undef);
1046              
1047 1         2 eval { local $^W = 0; shutdown($self->[HANDLE_STDIN], 1) };
  1         18  
  1         19  
1048 1 50 33     11 if ($@ or $self->[HANDLE_STDIN] != $self->[HANDLE_STDOUT]) {
1049 1         6 close $self->[HANDLE_STDIN];
1050             }
1051              
1052 1         4 $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 10     10 1 6875 $_[0]->[OCTETS_STDIN];
1194             }
1195              
1196             sub get_driver_out_messages {
1197 10     10 1 60 $_[0]->[DRIVER_STDIN]->get_out_messages_buffered();
1198             }
1199              
1200             sub ID {
1201 170     170 1 3043 $_[0]->[UNIQUE_ID];
1202             }
1203              
1204             sub PID {
1205 285     285 1 24871 $_[0]->[CHILD_PID];
1206             }
1207              
1208             sub kill {
1209 2     2 1 4225 my ($self, $signal) = @_;
1210 2 50       22 $signal = 'TERM' unless defined $signal;
1211 2 50       10 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 2         4 eval { kill $signal, $self->[CHILD_PID] };
  2         103  
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 867     867   1406 my ($dest,$mode,$fspec) = @_;
1270 867 100       1951 return unless defined $fspec;
1271 6 50       30 if(ref $fspec) {
1272 6 50       24 if (ref $fspec eq 'GLOB') {
1273 6         174 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   216 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       504 if(defined $stdin_read) {
1290 48 50       3133 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       418 if(defined $stdout_write) {
1297 47 50       7664 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       301 if(defined $stderr_write) {
1303 32 50       516 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__