File Coverage

blib/lib/POE/Wheel/Run.pm
Criterion Covered Total %
statement 372 562 66.1
branch 213 384 55.4
condition 77 157 49.0
subroutine 30 45 66.6
pod 20 21 95.2
total 712 1169 60.9


line stmt bran cond sub pod time code
1             package POE::Wheel::Run;
2              
3 71     71   47929 use strict;
  71         146  
  71         3729  
4              
5 71     71   353 use vars qw($VERSION @ISA);
  71         103  
  71         22781  
6             $VERSION = '1.367'; # NOTE - Should be #.### (three decimal places)
7              
8 71     71   470 use Carp qw(carp croak);
  71         147  
  71         6029  
9 71         2122 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   405 );
  71         126  
13              
14 71     71   9701 use POE qw( Wheel Pipe::TwoWay Pipe::OneWay Driver::SysRW Filter::Line );
  71         124  
  71         656  
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   572 die "$^O does not support fork()\n" if $^O eq 'MacOS';
25              
26 71         405 local $SIG{'__DIE__'} = 'DEFAULT';
27 71         142 eval { require IO::Pty; };
  71         70591  
28 71 50       593777 if ($@) {
29 0         0 eval '
30             sub PTY_AVAILABLE () { 0 }
31             sub TIOCSWINSZ_AVAILABLE () { 0 }
32             ';
33             }
34             else {
35 71         2390 IO::Pty->import();
36 71         4256 eval 'sub PTY_AVAILABLE () { 1 }';
37              
38 71         16330 eval { require IO::Tty; };
  71         715  
39 71 50       328 if ($@) {
40 0         0 eval 'sub TIOCSWINSZ_AVAILABLE () { 0 }';
41             }
42             else {
43 71         430 IO::Tty->import('TIOCSWINSZ');
44 71         14077 eval 'sub TIOCSWINSZ_AVAILABLE () { 1 }';
45             }
46             }
47              
48 71 50       487 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         149 my $max_open_fds;
74 71         152 eval {
75 71         565 $max_open_fds = sysconf(_SC_OPEN_MAX);
76             };
77 71 50       341 $max_open_fds = 1024 unless $max_open_fds;
78 71         2513 eval "sub MAX_OPEN_FDS () { $max_open_fds }";
79 71 50       648078 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 347     347 1 7909 my $type = shift;
121 347 50       1084 croak "$type needs an even number of parameters" if @_ & 1;
122 347         3166 my %params = @_;
123              
124 347 50 33     2489 croak "wheels no longer require a kernel reference as their first parameter"
125             if @_ and ref($_[0]) eq 'POE::Kernel';
126              
127 347 50       1190 croak "$type requires a working Kernel" unless defined $poe_kernel;
128              
129 347         905 my $program = delete $params{Program};
130 347 100       2570 croak "$type needs a Program parameter" unless defined $program;
131              
132 333         637 my $prog_args = delete $params{ProgramArgs};
133 333 100       1087 $prog_args = [] unless defined $prog_args;
134 333 50       1125 croak "ProgramArgs must be an ARRAY reference"
135             unless ref($prog_args) eq "ARRAY";
136              
137 333         695 my $priority_delta = delete $params{Priority};
138 333 50       959 $priority_delta = 0 unless defined $priority_delta;
139              
140 333         565 my $close_on_call = delete $params{CloseOnCall};
141 333 50       774 $close_on_call = 0 unless defined $close_on_call;
142              
143 333         1146 my $user_id = delete $params{User};
144 333         472 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 333         529 my $conduit = delete $params{Conduit};
157 333         392 my $stdio_type;
158 333 100       853 if (defined $conduit) {
159 56 100 100     2241 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       391 unless ($conduit =~ /^pty(-pipe)?$/) {
167 24         127 $stdio_type = $conduit;
168 24         160 $conduit = "pipe";
169             }
170             }
171             else {
172 277         659 $conduit = "pipe";
173             }
174              
175 319         709 my $winsize = delete $params{Winsize};
176              
177 319 50       828 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 319         724 my $stdin_event = delete $params{StdinEvent};
195 319         615 my $stdout_event = delete $params{StdoutEvent};
196 319         677 my $stderr_event = delete $params{StderrEvent};
197              
198 319 50 66     1192 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 319   33     4456 my $stdio_driver = delete $params{StdioDriver} || POE::Driver::SysRW->new();
207 319   33     1761 my $stdin_driver = delete $params{StdinDriver} || $stdio_driver;
208 319   33     1399 my $stdout_driver = delete $params{StdoutDriver} || $stdio_driver;
209 319   33     1824 my $stderr_driver = delete $params{StderrDriver} || POE::Driver::SysRW->new();
210              
211 319         606 my $stdio_filter = delete $params{Filter};
212 319         583 my $stdin_filter = delete $params{StdinFilter};
213 319         575 my $stdout_filter = delete $params{StdoutFilter};
214 319         596 my $stderr_filter = delete $params{StderrFilter};
215              
216             #For optional redirection...
217 319         447 my $redir_err = delete $params{RedirectStderr};
218 319         539 my $redir_out = delete $params{RedirectStdout};
219 319         618 my $redir_in = delete $params{RedirectStdin};
220 319         498 my $redir_output = delete $params{RedirectOutput};
221              
222 319         506 my $no_stdin = delete $params{NoStdin};
223              
224 319 100       1019 if(defined $redir_output) {
225 2         16 $redir_out = $redir_err = $redir_output;
226             }
227              
228             #Sanity check. We can't wait for redirected filehandles
229 319 100 66     3828 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         1358 croak("Redirect* and *Event stdio options are mutually exclusive");
233             }
234              
235 305 100       847 if (defined $stdio_filter) {
236 14 50       1442 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 291         2301 $stdio_filter = delete $params{StdioFilter};
244             }
245 291 100       2712 $stdio_filter = POE::Filter::Line->new(Literal => "\n")
246             unless defined $stdio_filter;
247              
248 291 100       931 $stdin_filter = $stdio_filter unless defined $stdin_filter;
249 291 100       793 $stdout_filter = $stdio_filter unless defined $stdout_filter;
250              
251 291 50 66     1229 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 291 100       1433 $stderr_filter = POE::Filter::Line->new(Literal => "\n")
257             unless defined $stderr_filter;
258             }
259              
260 291 50 66     2229 croak "$type needs either StdioFilter or StdinFilter when using StdinEvent"
261             if defined($stdin_event) and not defined($stdin_filter);
262 291 50 66     1775 croak "$type needs either StdioFilter or StdoutFilter when using StdoutEvent"
263             if defined($stdout_event) and not defined($stdout_filter);
264 291 50 66     1705 croak "$type needs a StderrFilter when using StderrEvent"
265             if defined($stderr_event) and not defined($stderr_filter);
266              
267 291         714 my $error_event = delete $params{ErrorEvent};
268 291         643 my $close_event = delete $params{CloseEvent};
269              
270 291         462 my $no_setsid = delete $params{NoSetSid};
271 291         504 my $no_setpgrp = delete $params{NoSetPgrp};
272              
273             # Make sure the user didn't pass in parameters we're not aware of.
274 291 50       979 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 291 100       1159 unless (ref($program) eq 'CODE') {
283 249 50 33     2297 croak "Someone has closed or moved STDIN... exec() won't find it"
284             unless defined fileno(STDIN) && fileno(STDIN) == 0;
285 249 50 33     2550 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     2363 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 291         473 $stdin_read, $stdout_write, $stdout_read, $stdin_write,
293             $stderr_read, $stderr_write,
294             );
295              
296 291         1668 _filespec_to_fh(\$stdin_read, "<", $redir_in);
297 291 100       737 if($redir_output) {
298 2         12 _filespec_to_fh(\$stdout_write, ">", $redir_output);
299 2         17 _filespec_to_fh(\$stderr_write, ">", $stdout_write);
300             } else {
301 289         825 _filespec_to_fh(\$stdout_write, ">", $redir_out);
302 289         708 _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 291         5225 my ($sem_pipe_read, $sem_pipe_write) = POE::Pipe::OneWay->new();
309 291 50       31335 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 291 100 66     2428 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 289 100       2008 if ($conduit =~ /^pty(-pipe)?$/) {
    50          
320 18         44 croak "IO::Pty is not available" unless PTY_AVAILABLE;
321              
322 18 50 33     283 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         321 $stdin_write = $stdout_read = IO::Pty->new();
327 18 50       13302 croak "could not create master pty: $!" unless defined $stdout_read;
328 18 100       83 if ($conduit eq "pty-pipe") {
329 8         73 ($stderr_read, $stderr_write) = POE::Pipe::OneWay->new();
330 8 50 33     590 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 271         2767 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 813         1664 my ($redir_ref,$rfd_ref,$wfd_ref,$evname, $prettyprint) = @$_;
348 813 100 66     4027 if(defined $evname && (!defined $$redir_ref)) {
349 589         2869 ($$rfd_ref,$$wfd_ref) = POE::Pipe::OneWay->new();
350 589 50 33     32689 croak "could not make $prettyprint pipe: $!"
351             unless defined $$rfd_ref and defined $$wfd_ref;
352             }
353             }
354 271 100 66     3007 unless (defined($redir_in) or $no_stdin) {
355 269         1655 ($stdin_read, $stdin_write) = POE::Pipe::OneWay->new();
356 269 50 33     17027 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 291         485 my $must_unmask;
369 291 50       2441 if( $poe_kernel->can( '_data_sig_mask_all' ) ) {
370 291         1582 $poe_kernel->_data_sig_mask_all;
371 291         583 $must_unmask = 1;
372             }
373              
374             # Fork! Woo-hoo!
375 291         328395 my $pid = fork;
376              
377             # Child. Parent side continues after this block.
378 291 100       7940 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 47 50       3619 __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 47 50       1772 if (tied *STDIN) {
387 0         0 carp "Cannot redirect out of tied STDIN. Untying it";
388 0         0 untie *STDIN;
389             }
390              
391 47 50       1061 if (tied *STDOUT) {
392 0         0 carp "Cannot redirect into tied STDOUT. Untying it";
393 0         0 untie *STDOUT;
394             }
395              
396 47 100       1173 if (tied *STDERR) {
397 1         687 carp "Cannot redirect into tied STDERR. Untying it";
398 1         270 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 47 100       1843 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       1912 eval 'setsid()' unless $no_setsid;
408              
409             # Acquire a controlling terminal. Program 19.3, APITUE.
410 4         102 $stdin_write->make_slave_controlling_terminal();
411              
412             # Open the slave side of the pty.
413 4         3003 $stdin_read = $stdout_write = $stdin_write->slave();
414 4 50       126 __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       69 $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         85 $stdin_read->set_raw();
423              
424 4         2785 if (TIOCSWINSZ_AVAILABLE) {
425 4 50       64 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 43 50       18745 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 47         1942 my @safe_signals = $poe_kernel->_data_sig_get_safe_signals();
445 47         6377 @SIG{@safe_signals} = ("DEFAULT") x @safe_signals;
446 47 50       1467 $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 47 50       568 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 47 50       525 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 47 50       475 if (defined $user_id) {
480 0         0 $< = $> = $user_id;
481             }
482              
483             # Close what the child won't need.
484 47 50       1389 close $stdin_write if defined $stdin_write;
485 47 100       555 close $stdout_read if defined $stdout_read;
486 47 100       729 close $stderr_read if defined $stderr_read;
487              
488 47 50       503 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 47         2018 __PACKAGE__->_redirect_child_stdio_sanely(
496             $stdin_read, $stdout_write, $stderr_write
497             );
498             }
499              
500             # Make STDOUT and/or STDERR auto-flush.
501 47         615 select STDERR; $| = 1;
  47         585  
502 47         469 select STDOUT; $| = 1;
  47         3545  
503              
504             # The child doesn't need to read from the semaphore pipe.
505 47         263 $sem_pipe_read = undef;
506              
507             # Run Perl code. This is fairly consistent across most systems.
508              
509 47 50       1207 if (ref($program) eq 'CODE') {
510              
511             # Tell the parent that the stdio has been set up.
512 0         0 print $sem_pipe_write "go\n";
513 0         0 close $sem_pipe_write;
514              
515             # Close any close-on-exec file descriptors. Except STDIN,
516             # STDOUT, and STDERR, of course.
517 0 0       0 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 0         0 eval { $program->(@$prog_args) };
  0         0  
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       4716 $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         19483 print $sem_pipe_write "go\n";
552 47         3490 close $sem_pipe_write;
553              
554             # exec(ARRAY)
555 47 50       498 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 244 100       7007 defined($stdin_read) and close $stdin_read;
570 244 100       3308 defined($stdout_write) and close $stdout_write;
571 244 100       2437 defined($stderr_write) and close $stderr_write;
572              
573              
574              
575             # Also close any slave ptys
576 244 100 100     7954 $stdout_read->close_slave() if (
577             defined $stdout_read and ref($stdout_read) eq 'IO::Pty'
578             );
579              
580 244 50 66     4196 $stderr_read->close_slave() if (
581             defined $stderr_read and ref($stderr_read) eq 'IO::Pty'
582             );
583              
584 244         823 my $active_count = 0;
585 244 100 66     2713 $active_count++ if $stdout_event and $stdout_read;
586 244 100 66     2584 $active_count++ if $stderr_event and $stderr_read;
587              
588 244         11678 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 244 50       7450 $poe_kernel->_data_sig_unmask_all if $must_unmask;
622              
623             # Wait here while the child sets itself up.
624 244         1356 $sem_pipe_write = undef;
625             {
626 244         6981 local $/ = "\n"; # TODO - Needed?
  244         7401  
627 244         555023 my $chldout = <$sem_pipe_read>;
628 244         1174 chomp $chldout;
629 244 50       2702 $self->[MSWIN32_GROUP_PID] = $chldout if $chldout ne 'go';
630             }
631 244         5785 close $sem_pipe_read;
632              
633 244 100       6277 $self->_define_stdin_flusher() if defined $stdin_write;
634 244 100       3189 $self->_define_stdout_reader() if defined $stdout_read;
635 244 100       2157 $self->_define_stderr_reader() if defined $stderr_read;
636              
637 244         10593 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 240     240   698 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 240         1872 my $unique_id = $self->[UNIQUE_ID];
650 240         584 my $driver = $self->[DRIVER_STDIN];
651 240         674 my $error_event = \$self->[ERROR_EVENT];
652 240         633 my $close_event = \$self->[CLOSE_EVENT];
653 240         428 my $stdin_filter = $self->[FILTER_STDIN];
654 240         2657 my $stdin_event = \$self->[EVENT_STDIN];
655 240         478 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 240         661 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   189 0 && CRIMSON_SCOPE_HACK('<');
667             # subroutine starts here
668 146         427 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
669              
670 146         747 $$stdin_octets = $driver->flush($handle);
671              
672             # When you can't write, nothing else matters.
673 146 50       1045 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       362 unless ($$stdin_octets) {
687 146         666 $k->select_pause_write($handle);
688 146 100       978 $$stdin_event && $k->call($me, $$stdin_event, $unique_id);
689             }
690             }
691             }
692 240         12722 );
693              
694 240         4633 $poe_kernel->select_write($self->[HANDLE_STDIN], $self->[STATE_STDIN]);
695              
696             # Pause the write select immediately, unless output is pending.
697 240 50       2841 $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   511 my $self = shift;
709              
710             # Can't do anything if we don't have a handle.
711 237 50       831 return unless defined $self->[HANDLE_STDOUT];
712              
713             # No event? Unregister the handler and leave.
714 237         664 my $stdout_event = \$self->[EVENT_STDOUT];
715 237 50       716 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         687 my $unique_id = $self->[UNIQUE_ID];
723 237         501 my $driver = $self->[DRIVER_STDOUT];
724 237         422 my $stdout_filter = $self->[FILTER_STDOUT];
725              
726             # These can change without redefining the callback since they're
727             # enclosed by reference.
728 237         463 my $is_active = \$self->[IS_ACTIVE];
729 237         443 my $close_event = \$self->[CLOSE_EVENT];
730 237         411 my $error_event = \$self->[ERROR_EVENT];
731              
732             # Register the select-read handler for STDOUT.
733 237 100 66     6286 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   385 0 && CRIMSON_SCOPE_HACK('<');
742              
743             # subroutine starts here
744 241         1010 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
745 241 100       1764 if (defined(my $raw_input = $driver->get($handle))) {
746 57         296 $stdout_filter->get_one_start($raw_input);
747 57         82 while (1) {
748 114         401 my $next_rec = $stdout_filter->get_one();
749 114 100       544 last unless @$next_rec;
750 57         135 foreach my $cooked_input (@$next_rec) {
751 57         277 $k->call($me, $$stdout_event, $cooked_input, $unique_id);
752             }
753             }
754             }
755             else {
756 184 100       1299 $$error_event and $k->call(
757             $me, $$error_event,
758             'read', ($!+0), $!, $unique_id, 'STDOUT'
759             );
760 184 100       639 unless (--$$is_active) {
761 121 100       717 $k->call( $me, $$close_event, $unique_id )
762             if defined $$close_event;
763             }
764 184         1168 $k->select_read($handle);
765             }
766             }
767 211         4439 );
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   41 0 && CRIMSON_SCOPE_HACK('<');
777              
778             # subroutine starts here
779 28         92 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
780 28 100       234 if (defined(my $raw_input = $driver->get($handle))) {
781 18         26 foreach my $cooked_input (@{$stdout_filter->get($raw_input)}) {
  18         109  
782 16         87 $k->call($me, $$stdout_event, $cooked_input, $unique_id);
783             }
784             }
785             else {
786 10 50       104 $$error_event and
787             $k->call(
788             $me, $$error_event,
789             'read', ($!+0), $!, $unique_id, 'STDOUT'
790             );
791 10 100       43 unless (--$$is_active) {
792 7 50       42 $k->call( $me, $$close_event, $unique_id )
793             if defined $$close_event;
794             }
795 10         50 $k->select_read($handle);
796             }
797             }
798 26         575 );
799             }
800              
801             # register the state's select
802 237         1184 $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   308 my $self = shift;
811              
812             # Can't do anything if we don't have a handle.
813 157 50       572 return unless defined $self->[HANDLE_STDERR];
814              
815             # No event? Unregister the handler and leave.
816 157         367 my $stderr_event = \$self->[EVENT_STDERR];
817 157 50       473 unless ($$stderr_event) {
818 0         0 $poe_kernel->select_read($self->[HANDLE_STDERR]);
819 0         0 return;
820             }
821              
822 157         766 my $unique_id = $self->[UNIQUE_ID];
823 157         374 my $driver = $self->[DRIVER_STDERR];
824 157         347 my $stderr_filter = $self->[FILTER_STDERR];
825              
826             # These can change without redefining the callback since they're
827             # enclosed by reference.
828 157         389 my $error_event = \$self->[ERROR_EVENT];
829 157         310 my $close_event = \$self->[CLOSE_EVENT];
830 157         314 my $is_active = \$self->[IS_ACTIVE];
831              
832             # Register the select-read handler for STDERR.
833 157 100 66     2308 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   323 0 && CRIMSON_SCOPE_HACK('<');
842              
843             # subroutine starts here
844 213         702 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
845 213 100       1555 if (defined(my $raw_input = $driver->get($handle))) {
846 104         653 $stderr_filter->get_one_start($raw_input);
847 104         149 while (1) {
848 202         821 my $next_rec = $stderr_filter->get_one();
849 202 100       865 last unless @$next_rec;
850 98         272 foreach my $cooked_input (@$next_rec) {
851 98         712 $k->call($me, $$stderr_event, $cooked_input, $unique_id);
852             }
853             }
854             }
855             else {
856 109 100       1153 $$error_event and $k->call(
857             $me, $$error_event,
858             'read', ($!+0), $!, $unique_id, 'STDERR'
859             );
860 109 100       347 unless (--$$is_active) {
861 63 50       353 $k->call( $me, $$close_event, $unique_id )
862             if defined $$close_event;
863             }
864 109         474 $k->select_read($handle);
865             }
866             }
867 137         2505 );
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   20 0 && CRIMSON_SCOPE_HACK('<');
877              
878             # subroutine starts here
879 14         64 my ($k, $me, $handle) = @_[KERNEL, SESSION, ARG0];
880 14 100       80 if (defined(my $raw_input = $driver->get($handle))) {
881 8         18 foreach my $cooked_input (@{$stderr_filter->get($raw_input)}) {
  8         51  
882 4         23 $k->call($me, $$stderr_event, $cooked_input, $unique_id);
883             }
884             }
885             else {
886 6 50       60 $$error_event and $k->call(
887             $me, $$error_event,
888             'read', ($!+0), $!, $unique_id, 'STDERR'
889             );
890 6 100       27 unless (--$$is_active) {
891 3 50       20 $k->call( $me, $$close_event, $unique_id )
892             if defined $$close_event;
893             }
894 6         34 $k->select_read($handle);
895             }
896             }
897 20         554 );
898             }
899              
900             # Register the state's select.
901 157         623 $poe_kernel->select_read($self->[HANDLE_STDERR], $self->[STATE_STDERR]);
902             }
903              
904             #------------------------------------------------------------------------------
905             # Redefine events.
906              
907             sub event {
908 120     120 1 1288 my $self = shift;
909 120 50       463 push(@_, undef) if (scalar(@_) & 1);
910              
911 120         232 my ($redefine_stdin, $redefine_stdout, $redefine_stderr) = (0, 0, 0);
912              
913 120         433 while (@_) {
914 294         941 my ($name, $event) = splice(@_, 0, 2);
915              
916 294 100       940 if ($name eq 'StdinEvent') {
    100          
    100          
    100          
    50          
917 60         118 $self->[EVENT_STDIN] = $event;
918 60         162 $redefine_stdin = 1;
919             }
920             elsif ($name eq 'StdoutEvent') {
921 60         152 $self->[EVENT_STDOUT] = $event;
922 60         150 $redefine_stdout = 1;
923             }
924             elsif ($name eq 'StderrEvent') {
925 54 50       154 if ($self->[CONDUIT_TYPE] ne 'pty') {
926 54         68 $self->[EVENT_STDERR] = $event;
927 54         124 $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         166 $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         167 my $active_count = 0;
946 120 50 33     844 $active_count++ if $self->[EVENT_STDOUT] and $self->[HANDLE_STDOUT];
947 120 100 66     487 $active_count++ if $self->[EVENT_STDERR] and $self->[HANDLE_STDERR];
948 120         282 $self->[IS_ACTIVE] = $active_count;
949             }
950              
951             #------------------------------------------------------------------------------
952             # Destroy the wheel.
953              
954             sub DESTROY {
955 203     203   5648 my $self = shift;
956              
957 203 100       1576 return if(ref POE::Kernel->get_active_session eq 'POE::Kernel');
958              
959             # Turn off the STDIN thing.
960 201 100       870 if ($self->[HANDLE_STDIN]) {
961 197         1058 $poe_kernel->select_write($self->[HANDLE_STDIN]);
962 197         580 $self->[HANDLE_STDIN] = undef;
963             }
964              
965 201 100       5450 if ($self->[STATE_STDIN]) {
966 199         1223 $poe_kernel->state($self->[STATE_STDIN]);
967 199         455 $self->[STATE_STDIN] = undef;
968             }
969              
970 201 100       774 if ($self->[HANDLE_STDOUT]) {
971 196         864 $poe_kernel->select_read($self->[HANDLE_STDOUT]);
972 196         459 $self->[HANDLE_STDOUT] = undef;
973             }
974 201 100       2688 if ($self->[STATE_STDOUT]) {
975 196         782 $poe_kernel->state($self->[STATE_STDOUT]);
976 196         517 $self->[STATE_STDOUT] = undef;
977             }
978              
979 201 100       701 if ($self->[HANDLE_STDERR]) {
980 118         467 $poe_kernel->select_read($self->[HANDLE_STDERR]);
981 118         268 $self->[HANDLE_STDERR] = undef;
982             }
983 201 100       1362 if ($self->[STATE_STDERR]) {
984 118         383 $poe_kernel->state($self->[STATE_STDERR]);
985 118         224 $self->[STATE_STDERR] = undef;
986             }
987              
988 201         1224 &POE::Wheel::free_wheel_id($self->[UNIQUE_ID]);
989             }
990              
991             #------------------------------------------------------------------------------
992             # Queue input for the child process.
993              
994             sub put {
995 200     200 1 6747 my ($self, @chunks) = @_;
996              
997             # Avoid big bada boom if someone put()s on a dead wheel.
998 200 100       1120 croak "Called put() on a wheel without an open STDIN handle" unless (
999             $self->[HANDLE_STDIN]
1000             );
1001              
1002 198 50       3117 if (
1003             $self->[OCTETS_STDIN] = # assignment on purpose
1004             $self->[DRIVER_STDIN]->put($self->[FILTER_STDIN]->put(\@chunks))
1005             ) {
1006 198         1071 $poe_kernel->select_resume_write($self->[HANDLE_STDIN]);
1007             }
1008              
1009             # No watermark.
1010 198         737 return 0;
1011             }
1012              
1013             #------------------------------------------------------------------------------
1014             # Pause and resume various input events.
1015              
1016             sub pause_stdout {
1017 2     2 1 4227 my $self = shift;
1018 2 50       15 return unless defined $self->[HANDLE_STDOUT];
1019 2         47 $poe_kernel->select_pause_read($self->[HANDLE_STDOUT]);
1020             }
1021              
1022             sub pause_stderr {
1023 2     2 1 7563 my $self = shift;
1024 2 50       14 return unless defined $self->[HANDLE_STDERR];
1025 2         17 $poe_kernel->select_pause_read($self->[HANDLE_STDERR]);
1026             }
1027              
1028             sub resume_stdout {
1029 2     2 1 520 my $self = shift;
1030 2 50       11 return unless defined $self->[HANDLE_STDOUT];
1031 2         15 $poe_kernel->select_resume_read($self->[HANDLE_STDOUT]);
1032             }
1033              
1034             sub resume_stderr {
1035 2     2 1 3736 my $self = shift;
1036 2 50       13 return unless defined $self->[HANDLE_STDERR];
1037 2         15 $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 2889 my $self = shift;
1043 2 50       13 return unless defined $self->[HANDLE_STDIN];
1044              
1045 2         14 $poe_kernel->select_write($self->[HANDLE_STDIN], undef);
1046              
1047 2         11 eval { local $^W = 0; shutdown($self->[HANDLE_STDIN], 1) };
  2         28  
  2         37  
1048 2 50 33     23 if ($@ or $self->[HANDLE_STDIN] != $self->[HANDLE_STDOUT]) {
1049 2         13 close $self->[HANDLE_STDIN];
1050             }
1051              
1052 2         11 $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 14362 $_[0]->[OCTETS_STDIN];
1194             }
1195              
1196             sub get_driver_out_messages {
1197 20     20 1 118 $_[0]->[DRIVER_STDIN]->get_out_messages_buffered();
1198             }
1199              
1200             sub ID {
1201 170     170 1 3289 $_[0]->[UNIQUE_ID];
1202             }
1203              
1204             sub PID {
1205 289     289 1 17682 $_[0]->[CHILD_PID];
1206             }
1207              
1208             sub kill {
1209 4     4 1 7490 my ($self, $signal) = @_;
1210 4 50       37 $signal = 'TERM' unless defined $signal;
1211 4 50       22 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         9 eval { kill $signal, $self->[CHILD_PID] };
  4         3544  
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 873     873   1629 my ($dest,$mode,$fspec) = @_;
1270 873 100       2081 return unless defined $fspec;
1271 6 50       22 if(ref $fspec) {
1272 6 50       23 if (ref $fspec eq 'GLOB') {
1273 6         172 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 47     47   306 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 47 50       535 if(defined $stdin_read) {
1290 47 50       3091 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 47 100       7478 if(defined $stdout_write) {
1297 46 50       860 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 47 100       10678 if(defined $stderr_write) {
1303 31 50       762 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__