1POE::Wheel::Run(3) User Contributed Perl Documentation POE::Wheel::Run(3)
2
3
4
6 POE::Wheel::Run - portably run blocking code and programs in
7 subprocesses
8
10 #!/usr/bin/perl
11
12 use warnings;
13 use strict;
14
15 use POE qw( Wheel::Run );
16
17 POE::Session->create(
18 inline_states => {
19 _start => \&on_start,
20 got_child_stdout => \&on_child_stdout,
21 got_child_stderr => \&on_child_stderr,
22 got_child_close => \&on_child_close,
23 got_child_signal => \&on_child_signal,
24 }
25 );
26
27 POE::Kernel->run();
28 exit 0;
29
30 sub on_start {
31 my $child = POE::Wheel::Run->new(
32 Program => [ "/bin/ls", "-1", "/" ],
33 StdoutEvent => "got_child_stdout",
34 StderrEvent => "got_child_stderr",
35 CloseEvent => "got_child_close",
36 );
37
38 $_[KERNEL]->sig_child($child->PID, "got_child_signal");
39
40 # Wheel events include the wheel's ID.
41 $_[HEAP]{children_by_wid}{$child->ID} = $child;
42
43 # Signal events include the process ID.
44 $_[HEAP]{children_by_pid}{$child->PID} = $child;
45
46 print(
47 "Child pid ", $child->PID,
48 " started as wheel ", $child->ID, ".\n"
49 );
50 }
51
52 # Wheel event, including the wheel's ID.
53 sub on_child_stdout {
54 my ($stdout_line, $wheel_id) = @_[ARG0, ARG1];
55 my $child = $_[HEAP]{children_by_wid}{$wheel_id};
56 print "pid ", $child->PID, " STDOUT: $stdout_line\n";
57 }
58
59 # Wheel event, including the wheel's ID.
60 sub on_child_stderr {
61 my ($stderr_line, $wheel_id) = @_[ARG0, ARG1];
62 my $child = $_[HEAP]{children_by_wid}{$wheel_id};
63 print "pid ", $child->PID, " STDERR: $stderr_line\n";
64 }
65
66 # Wheel event, including the wheel's ID.
67 sub on_child_close {
68 my $wheel_id = $_[ARG0];
69 my $child = delete $_[HEAP]{children_by_wid}{$wheel_id};
70
71 # May have been reaped by on_child_signal().
72 unless (defined $child) {
73 print "wid $wheel_id closed all pipes.\n";
74 return;
75 }
76
77 print "pid ", $child->PID, " closed all pipes.\n";
78 delete $_[HEAP]{children_by_pid}{$child->PID};
79 }
80
81 sub on_child_signal {
82 print "pid $_[ARG1] exited with status $_[ARG2].\n";
83 my $child = delete $_[HEAP]{children_by_pid}{$_[ARG1]};
84
85 # May have been reaped by on_child_close().
86 return unless defined $child;
87
88 delete $_[HEAP]{children_by_wid}{$child->ID};
89 }
90
92 POE::Wheel::Run executes a program or block of code in a subprocess,
93 created the usual way: using fork(). The parent process may exchange
94 information with the child over the child's STDIN, STDOUT and STDERR
95 filehandles.
96
97 In the parent process, the POE::Wheel::Run object represents the child
98 process. It has methods such as PID() and kill() to query and manage
99 the child process.
100
101 POE::Wheel::Run's put() method sends data to the child's STDIN. Child
102 output on STDOUT and STDERR may be dispatched as events within the
103 parent, if requested.
104
105 POE::Wheel::Run can also notify the parent when the child has closed
106 its output filehandles. Some programs remain active, but they close
107 their output filehandles to indicate they are done writing.
108
109 A more reliable way to detect child exit is to use POE::Kernel's
110 sig_child() method to wait for the wheel's process to be reaped. It is
111 in fact vital to use sig_child() in all circumstances since without it,
112 POE will not try to reap child processes.
113
114 Failing to use sig_child() has in the past led to wedged machines.
115 Long-running programs have leaked processes, eventually consuming all
116 available slots in the process table and requiring reboots.
117
118 Because process leaks are so severe, POE::Kernel will check for this
119 condition on exit and display a notice if it finds that processes are
120 leaking. Developers should heed these warnings.
121
122 POE::Wheel::Run communicates with the child process in a line-based
123 fashion by default. Programs may override this by specifying some
124 other POE::Filter object in "StdinFilter", "StdoutFilter",
125 "StdioFilter" and/or "StderrFilter".
126
128 Constructor
129 POE::Wheel subclasses tend to perform a lot of setup so that they run
130 lighter and faster. POE::Wheel::Run's constructor is no exception.
131
132 new
133
134 new() creates and returns a new POE::Wheel::Run object. If it's
135 successful, the object will represent a child process with certain
136 specified qualities. It also provides an OO- and event-based interface
137 for asynchronously interacting with the process.
138
139 Conduit
140
141 Conduit specifies the inter-process communications mechanism that will
142 be used to pass data between the parent and child process. Conduit may
143 be one of "pipe", "socketpair", "inet", "pty", or "pty-pipe".
144 POE::Wheel::Run will use the most appropriate Conduit for the run-time
145 (not the compile-time) operating system, but this varies from one OS to
146 the next.
147
148 Internally, POE::Wheel::Run passes the Conduit type to
149 POE::Pipe::OneWay and POE::Pipe::TwoWay. These helper classes were
150 created to make IPC portable and reusable. They do not require the
151 rest of POE.
152
153 Three Conduit types use pipes or pipelike inter-process communication:
154 "pipe", "socketpair" and "inet". They determine whether the internal
155 IPC uses pipe(), socketpair() or Internet sockets. These Conduit
156 values are passed through to POE::Pipe::OneWay or POE::Pipe::TwoWay
157 internally.
158
159 The "pty" conduit type runs the child process under a pseudo-tty, which
160 is created by IO::Pty. Pseudo-ttys (ptys) convince child processes
161 that they are interacting with terminals rather than pipes. This may
162 be used to trick programs like ssh into believing it's secure to prompt
163 for a password, although passphraseless identities might be better for
164 that.
165
166 The "pty" conduit cannot separate STDERR from STDOUT, but the "pty-
167 pipe" mode can.
168
169 The "pty-pipe" conduit uses a pty for STDIN and STDOUT and a one-way
170 pipe for STDERR. The additional pipe keeps STDERR output separate from
171 STDOUT.
172
173 The IO::Pty module is only loaded if "pty" or "pty-pipe" is used. It's
174 not a dependency until it's actually needed.
175
176 Winsize
177
178 Winsize sets the child process' terminal size. Its value should be an
179 arrayref with four elements. The first two elements must be the number
180 of lines and columns for the child's terminal window, respectively.
181 The second pair of elements describe the terminal's X and Y dimensions
182 in pixels. If the last pair is missing, they will be calculated from
183 the lines and columns using a 9x16 cell size.
184
185 $_[HEAP]{child} = POE::Wheel::Run->new(
186 # ... among other things ...
187 Winsize => [ 25, 80, 720, 400 ],
188 );
189
190 Winsize is only valid for conduits that use pseudo-ttys: "pty" and
191 "pty-pipe". Other conduits don't simulate terminals, so they don't
192 have window sizes.
193
194 Winsize defaults to the parent process' window size, assuming the
195 parent process has a terminal to query.
196
197 CloseOnCall
198
199 CloseOnCall, when true, turns on close-on-exec emulation for
200 subprocesses that don't actually call exec(). These would be instances
201 when the child is running a block of code rather than executing an
202 external program. For example:
203
204 $_[HEAP]{child} = POE::Wheel::Run->new(
205 # ... among other things ...
206 CloseOnCall => 1,
207 Program => \&some_function,
208 );
209
210 CloseOnCall is off (0) by default.
211
212 CloseOnCall works by closing all file descriptors greater than $^F in
213 the child process before calling the application's code. For more
214 details, please the discussion of $^F in perlvar.
215
216 StdioDriver
217
218 StdioDriver specifies a single POE::Driver object to be used for both
219 STDIN and STDOUT. It's equivalent to setting "StdinDriver" and
220 "StdoutDriver" to the same POE::Driver object.
221
222 POE::Wheel::Run will create and use a POE::Driver::SysRW driver of one
223 isn't specified. This is by far the most common use case, so it's the
224 default.
225
226 StdinDriver
227
228 "StdinDriver" sets the POE::Driver used to write to the child process'
229 STDIN IPC conduit. It is almost never needed. Omitting it will allow
230 POE::Wheel::Run to use an internally created POE::Driver::SysRW object.
231
232 StdoutDriver
233
234 "StdoutDriver" sets the POE::Driver object that will be used to read
235 from the child process' STDOUT conduit. It's almost never needed. If
236 omitted, POE::Wheel::Run will internally create and use a
237 POE::Driver::SysRW object.
238
239 StderrDriver
240
241 "StderrDriver" sets the driver that will be used to read from the child
242 process' STDERR conduit. As with "StdoutDriver", it's almost always
243 preferable to let POE::Wheel::Run instantiate its own driver.
244
245 CloseEvent
246
247 CloseEvent contains the name of an event that the wheel will emit when
248 the child process closes its last open output handle. This is a
249 consistent notification that the child is done sending output. Please
250 note that it does not signal when the child process has exited.
251 Programs should use sig_child() to detect that.
252
253 While it is impossible for ErrorEvent or StdoutEvent to happen after
254 CloseEvent, there is no such guarantee for CHLD, which may happen
255 before or after CloseEvent.
256
257 In addition to the usual POE parameters, each CloseEvent comes with one
258 of its own:
259
260 "ARG0" contains the wheel's unique ID. This can be used to keep
261 several child processes separate when they're managed by the same
262 session.
263
264 A sample close event handler:
265
266 sub close_state {
267 my ($heap, $wheel_id) = @_[HEAP, ARG0];
268
269 my $child = delete $heap->{child}->{$wheel_id};
270 print "Child ", $child->PID, " has finished.\n";
271 }
272
273 ErrorEvent
274
275 ErrorEvent contains the name of an event to emit if something fails.
276 It is optional; if omitted, the wheel will not notify its session if
277 any errors occur. However, POE::Wheel::Run->new() will still throw an
278 exception if it fails.
279
280 "ARG0" contains the name of the operation that failed. It may be
281 'read', 'write', 'fork', 'exec' or the name of some other function or
282 task. The actual values aren't yet defined. They will probably not
283 correspond so neatly to Perl builtin function names.
284
285 "ARG1" and "ARG2" hold numeric and string values for $!, respectively.
286 "$!" will eq "" for read error 0 (child process closed the file
287 handle).
288
289 "ARG3" contains the wheel's unique ID.
290
291 "ARG4" contains the name of the child filehandle that has the error.
292 It may be "STDIN", "STDOUT", or "STDERR". The sense of "ARG0" will be
293 the opposite of what you might normally expect for these handles. For
294 example, POE::Wheel::Run will report a "read" error on "STDOUT" because
295 it tried to read data from the child's STDOUT handle.
296
297 A sample error event handler:
298
299 sub error_state {
300 my ($operation, $errnum, $errstr, $wheel_id) = @_[ARG0..ARG3];
301 $errstr = "remote end closed" if $operation eq "read" and !$errnum;
302 warn "Wheel $wheel_id generated $operation error $errnum: $errstr\n";
303 }
304
305 Note that unless you deactivate the signal pipe, you might also see
306 "EIO" (5) error during read operations.
307
308 StdinEvent
309
310 StdinEvent contains the name of an event that Wheel::Run emits whenever
311 everything queued by its put() method has been flushed to the child's
312 STDIN handle. It is the equivalent to POE::Wheel::ReadWrite's
313 FlushedEvent.
314
315 StdinEvent comes with only one additional parameter: "ARG0" contains
316 the unique ID for the wheel that sent the event.
317
318 StdoutEvent
319
320 StdoutEvent contains the name of an event that Wheel::Run emits
321 whenever the child process writes something to its STDOUT filehandle.
322 In other words, whatever the child prints to STDOUT, the parent
323 receives a StdoutEvent---provided that the child prints something
324 compatible with the parent's StdoutFilter.
325
326 StdoutEvent comes with two parameters. "ARG0" contains the information
327 that the child wrote to STDOUT. "ARG1" holds the unique ID of the
328 wheel that read the output.
329
330 sub stdout_state {
331 my ($heap, $input, $wheel_id) = @_[HEAP, ARG0, ARG1];
332 print "Child process in wheel $wheel_id wrote to STDOUT: $input\n";
333 }
334
335 StderrEvent
336
337 StderrEvent behaves exactly as StdoutEvent, except for data the child
338 process writes to its STDERR filehandle.
339
340 StderrEvent comes with two parameters. "ARG0" contains the information
341 that the child wrote to STDERR. "ARG1" holds the unique ID of the
342 wheel that read the output.
343
344 sub stderr_state {
345 my ($heap, $input, $wheel_id) = @_[HEAP, ARG0, ARG1];
346 print "Child process in wheel $wheel_id wrote to STDERR: $input\n";
347 }
348
349 RedirectStdout
350
351 This is a filehandle or filename to which standard output will be
352 redirected. It is an error to use this option together with
353 StdoutEvent. This is useful in case your program needs to have standard
354 I/O, but do not actually care for its contents to be visible to the
355 parent.
356
357 RedirectStderr
358
359 Just like RedirectStdout, but with standard error. It is an error to
360 use this together with StderrEvent
361
362 RedirectStdin
363
364 This is a filehandle or filename which the child process will use as
365 its standard input. It is an error to use this option with StdinEvent
366
367 RedirectOutput
368
369 This will redirect stderr and stdout to the same filehandle. This is
370 equivalent to do doing something like
371
372 $ something > /path/to/output 2>&1
373
374 in bourne shell.
375
376 NoStdin
377
378 While output filehandles will be closed if there are no events to be
379 received on them, stdin is open by default - because lack of an event
380 handler does not necessarily mean there is no desired input stream.
381 This option explicitly disables the creation of an IPC stdin conduit.
382
383 StdioFilter
384
385 StdioFilter, if used, must contain an instance of a POE::Filter
386 subclass. This filter describes how the parent will format put() data
387 for the child's STDIN, and how the parent will parse the child's
388 STDOUT.
389
390 If STDERR will also be parsed, then a separate StderrFilter will also
391 be needed.
392
393 StdioFilter defaults to a POE::Filter::Line instance, but only if both
394 StdinFilter and StdoutFilter are not specified. If either StdinFilter
395 or StdoutFilter is used, then StdioFilter is illegal.
396
397 StdinFilter
398
399 StdinFilter may be used to specify a particular STDIN serializer that
400 is different from the STDOUT parser. If specified, it conflicts with
401 StdioFilter. StdinFilter's value, if specified, must be an instance of
402 a POE::Filter subclass.
403
404 Without a StdinEvent, StdinFilter is illegal.
405
406 StdoutFilter
407
408 StdoutFilter may be used to specify a particular STDOUT parser that is
409 different from the STDIN serializer. If specified, it conflicts with
410 StdioFilter. StdoutFilter's value, if specified, must be an instance
411 of a POE::Filter subclass.
412
413 Without a StdoutEvent, StdoutFilter is illegal.
414
415 StderrFilter
416
417 StderrFilter may be used to specify a filter for a child process'
418 STDERR output. If omitted, POE::Wheel::Run will create and use its own
419 POE::Filter::Line instance, but only if a StderrEvent is specified.
420
421 Without a StderrEvent, StderrFilter is illegal.
422
423 Group
424
425 Group contains a numeric group ID that the child process should run
426 within. By default, the child process will run in the same group as
427 the parent.
428
429 Group is not fully portable. It may not work on systems that have no
430 concept of user groups. Also, the parent process may need to run with
431 elevated privileges for the child to be able to change groups.
432
433 User
434
435 User contains a numeric user ID that should own the child process. By
436 default, the child process will run as the same user as the parent.
437
438 User is not fully portable. It may not work on systems that have no
439 concept of users. Also, the parent process may need to run with
440 elevated privileges for the child to be able to change users.
441
442 NoSetSid
443
444 When true, NoSetSid disables setsid() in the child process. By
445 default, the child process calls setsid() is called so that it may
446 execute in a separate UNIX session.
447
448 This option is deprecated. As IO::Pty uses "setsid()" this module has
449 no control on whether it is invoked or not.
450
451 NoSetPgrp
452
453 When true, NoSetPgrp disables setprgp() in the child process. By
454 default, the child process calls setpgrp() to change its process group,
455 if the OS supports that.
456
457 setsid() is used instead of setpgrp() if Conduit is pty or pty-pipe.
458 See "NoSetSid".
459
460 Priority
461
462 Priority adjusts the child process' niceness or priority level,
463 depending on which (if any) the underlying OS supports. Priority
464 contains a numeric offset which will be added to the parent's priority
465 to determine the child's.
466
467 The priority offset may be negative, which in UNIX represents a higher
468 priority. However UNIX requires elevated privileges to increase a
469 process' priority.
470
471 Program
472
473 Program specifies the program to exec() or the block of code to run in
474 the child process. Program's type is significant.
475
476 If Program holds a scalar, its value will be executed as
477 exec($program). Shell metacharacters are significant, per exec(SCALAR)
478 semantics.
479
480 If Program holds an array reference, it will executed as
481 exec(@$program). As per exec(ARRAY), shell metacharacters will not be
482 significant.
483
484 If Program holds a code reference, that code will be called in the
485 child process. This mode allows POE::Wheel::Run to execute long-
486 running internal code asynchronously, while the usual modes execute
487 external programs. The child process will exit after that code is
488 finished, in such a way as to avoid DESTROY and END block execution.
489 See "Coderef Execution Side Effects" for more details.
490
491 perlfunc has more information about exec() and the different ways to
492 call it.
493
494 Please avoid calling exit() explicitly when executing a subroutine.
495 The child process inherits all objects from the parent, including ones
496 that may perform side effects. POE::Wheel::Run takes special care to
497 avoid object destructors and END blocks in the child process, but
498 calling exit() will trigger them.
499
500 ProgramArgs
501
502 If specified, ProgramArgs should refer to a list of parameters for the
503 program being run.
504
505 my @parameters = qw(foo bar baz); # will be passed to Program
506 ProgramArgs => \@parameters;
507
508 event EVENT_TYPE => EVENT_NAME, ...
509 event() allows programs to change the events that Wheel::Run emits when
510 certain activities occurs. EVENT_TYPE may be one of the event
511 parameters described in POE::Wheel::Run's constructor.
512
513 This example changes the events that $wheel emits for STDIN flushing
514 and STDOUT activity:
515
516 $wheel->event(
517 StdinEvent => 'new-stdin-event',
518 StdoutEvent => 'new-stdout-event',
519 );
520
521 Undefined EVENT_NAMEs disable events.
522
523 put RECORDS
524 put() queues up a list of RECORDS that will be sent to the child
525 process' STDIN filehandle. These records will first be serialized
526 according to the wheel's StdinFilter. The serialized RECORDS will be
527 flushed asynchronously once the current event handler returns.
528
529 get_stdin_filter
530 get_stind_filter() returns the POE::Filter object currently being used
531 to serialize put() records for the child's STDIN filehandle. The
532 return object may be used according to its own interface.
533
534 get_stdout_filter
535 get_stdout_filter() returns the POE::Filter object currently being used
536 to parse what the child process writes to STDOUT.
537
538 get_stderr_filter
539 get_stderr_filter() returns the POE::Filter object currently being used
540 to parse what the child process writes to STDERR.
541
542 set_stdio_filter FILTER_OBJECT
543 Set StdinFilter and StdoutFilter to the same new FILTER_OBJECT.
544 Unparsed STDOUT data will be parsed later by the new FILTER_OBJECT.
545 However, data already put() will remain serialized by the old filter.
546
547 set_stdin_filter FILTER_OBJECT
548 Set StdinFilter to a new FILTER_OBJECT. Data already put() will remain
549 serialized by the old filter.
550
551 set_stdout_filter FILTER_OBJECT
552 Set StdoutFilter to a new FILTER_OBJECT. Unparsed STDOUT data will be
553 parsed later by the new FILTER_OBJECT.
554
555 set_stderr_filter FILTER_OBJECT
556 Set StderrFilter to a new FILTER_OBJECT. Unparsed STDERR data will be
557 parsed later by the new FILTER_OBJECT.
558
559 pause_stdout
560 Pause reading of STDOUT from the child. The child process may block if
561 the STDOUT IPC conduit fills up. Reading may be resumed with
562 resume_stdout().
563
564 pause_stderr
565 Pause reading of STDERR from the child. The child process may block if
566 the STDERR IPC conduit fills up. Reading may be resumed with
567 resume_stderr().
568
569 resume_stdout
570 Resume reading from the child's STDOUT filehandle. This is only
571 meaningful if pause_stdout() has been called and remains in effect.
572
573 resume_stderr
574 Resume reading from the child's STDERR filehandle. This is only
575 meaningful if pause_stderr() has been called and remains in effect.
576
577 shutdown_stdin
578 shutdown_stdin() closes the child process' STDIN and stops the wheel
579 from reporting StdinEvent. It is extremely useful for running
580 utilities that expect to receive EOF on STDIN before they respond.
581
582 ID
583 ID() returns the wheel's unique ID. Every event generated by a
584 POE::Wheel::Run object includes a wheel ID so that it can be matched to
585 the wheel that emitted it. This lets a single session manage several
586 wheels without becoming confused about which one generated what event.
587
588 ID() is not the same as PID().
589
590 PID
591 PID() returns the process ID for the child represented by the
592 POE::Wheel::Run object. It's often used as a parameter to sig_child().
593
594 PID() is not the same as ID().
595
596 kill SIGNAL
597 POE::Wheel::Run's kill() method sends a SIGNAL to the child process the
598 object represents. kill() is often used to force a reluctant program
599 to terminate. SIGNAL is one of the operating signal names present in
600 %SIG.
601
602 kill() returns the number of processes successfully signaled: 1 on
603 success, or 0 on failure, since the POE::Wheel::Run object only affects
604 at most a single process.
605
606 kill() sends SIGTERM if SIGNAL is undef or omitted.
607
608 get_driver_out_messages
609 get_driver_out_messages() returns the number of put() records remaining
610 in whole or in part in POE::Wheel::Run's POE::Driver output queue. It
611 is often used to tell whether the wheel has more input for the child
612 process.
613
614 In most cases, StdinEvent may be used to trigger activity when all data
615 has been sent to the child process.
616
617 get_driver_out_octets
618 get_driver_out_octets() returns the number of serialized octets
619 remaining in POE::Wheel::Run's POE::Driver output queue. It is often
620 used to tell whether the wheel has more input for the child process.
621
623 MSWin32 Support
624 In the past POE::Wheel::Run did not support MSWin32 and users had to
625 use custom work-arounds. Then Chris Williams ( BINGOS ) arrived and
626 saved the day with his POE::Wheel::Run::Win32 module. After some
627 testing, it was decided to merge the win32 code into POE::Wheel::Run.
628 Everyone was happy!
629
630 However, after some investigation Apocalypse ( APOCAL ) found out that
631 in some situations it still didn't behave properly. The root cause was
632 that the win32 code path in POE::Wheel::Run didn't exit cleanly. This
633 means DESTROY and END blocks got executed! After talking with more
634 people, the solution was not pretty.
635
636 The problem is that there is no equivalent of POSIX::_exit() for
637 MSWin32. Hopefully, in a future version of Perl this can be fixed! In
638 the meantime, POE::Wheel::Run will use CORE::kill() to terminate the
639 child. However, this comes with a caveat: you will leak around 1KB per
640 exec. The code has been improved so the chance of this happening has
641 been reduced.
642
643 As of now the most reliable way to trigger this is to exec an invalid
644 binary. The definition of "invalid binary" depends on different things,
645 but what it means is that Win32::Job->spawn() failed to run. This will
646 force POE::Wheel::Run to use the workaround to exit the child. If this
647 happens, a very big warning will be printed to the STDERR of the child
648 and the parent process will receive it.
649
650 If you are a Perl MSWin32 hacker, PLEASE help us with this situation!
651 Go read rt.cpan.org bug #56417 and talk with us/p5p to see where you
652 can contribute.
653
654 Thanks again for your patience as we continue to improve
655 POE::Wheel::Run on MSWin32!
656
657 kill() and ClosedEvent on Windows
658
659 Windows will often fail to report EOF on pipes when subprocesses are
660 killed. The work-around is to catch the signal in the subprocess, and
661 exit normally:
662
663 my $child = POE::Wheel::Run->new(
664 Program => sub {
665 $SIG{INT} = sub { exit };
666 ...;
667 },
668 ...,
669 );
670
671 Be sure to kill() the subprocess using the same signal that it catches
672 and exits upon. Remember, not all signals can be caught by user code.
673
674 $child->kill("INT");
675
676 Execution Environment
677 It's common to scrub a child process' environment, so that only
678 required, secure values exist. This amounts to clearing the contents
679 of %ENV and repopulating it.
680
681 Environment scrubbing is easy when the child process is running a
682 subroutine, but it's not so easy---or at least not as intuitive---when
683 executing external programs.
684
685 The way we do it is to run a small subroutine in the child process that
686 performs the exec() call for us.
687
688 Program => \&exec_with_scrubbed_env,
689
690 sub exec_with_scrubbed_env {
691 delete @ENV{keys @ENV};
692 $ENV{PATH} = "/bin";
693 exec(@program_and_args);
694 }
695
696 That deletes everything from the environment and sets a simple, secure
697 PATH before executing a program.
698
699 Coderef Execution Side Effects
700 The child process is created by fork(), which duplicates the parent
701 process including a copy of POE::Kernel, all running Session instances,
702 events in the queue, watchers, open filehandles, and so on.
703
704 When executing an external program, the UNIX exec() call immediately
705 replaces the copy of the parent with a completely new program.
706
707 When executing internal coderefs, however, we must preserve the code
708 and any memory it might reference. This leads to some potential side
709 effects.
710
711 DESTROY and END Blocks Run Twice
712
713 Objects that were created in the parent process are copied into the
714 child. When the child exits normally, any DESTROY and END blocks are
715 executed there. Later, when the parent exits, they may run again.
716
717 POE::Wheel::Run takes steps to avoid running DESTROY and END blocks in
718 the child process. It uses POSIX::_exit() to bypass them. If that
719 fails, it may even kill() itself.
720
721 If an application needs to exit explicitly, for example to return an
722 error code to the parent process, then please use POSIX::_exit() rather
723 than Perl's core exit().
724
725 POE::Kernel's run() method was never called
726
727 This warning is displayed from POE::Kernel's DESTROY method. It's a
728 side effect of calling exit() in a child process that was started
729 before "POE::Kernel->run()" could be called. The child process
730 receives a copy of POE::Kernel where run() wasn't called, even if it
731 was called later in the parent process.
732
733 The most direct solution is to call POSIX::_exit() rather than exit().
734 This will bypass POE::Kernel's DESTROY, and the message it emits.
735
736 Running POE::Kernel in the Child
737
738 Calling "POE::Kernel->run()" in the child process effectively resumes
739 the copy of the parent process. This is rarely (if ever) desired.
740
741 More commonly, an application wants to run an entirely new POE::Kernel
742 instance in the child process. This is supported by first stop()ping
743 the copied instance, starting one or more new sessions, and calling
744 run() again. For example:
745
746 Program => sub {
747 # Wipe the existing POE::Kernel clean.
748 $poe_kernel->stop();
749
750 # Start a new session, or more.
751 POE::Session->create(
752 ...
753 );
754
755 # Run the new sessions.
756 POE::Kernel->run();
757 }
758
759 Strange things are bound to happen if the program does not call "stop"
760 in POE::Kernel before "run" in POE::Kernel. However this is vaguely
761 supported in case it's the right thing to do at the time.
762
764 POE::Wheel describes wheels in general.
765
766 The SEE ALSO section in POE contains a table of contents covering the
767 entire POE distribution.
768
770 POE::Wheel::Run's constructor should emit proper events when it fails.
771 Instead, it just dies, carps or croaks. This isn't necessarily bad; a
772 program can trap the death in new() and move on.
773
774 Priority is a delta, not an absolute niceness value.
775
776 It might be nice to specify User by name rather than just UID.
777
778 It might be nice to specify Group by name rather than just GID.
779
780 POE::Pipe::OneWay and Two::Way don't require the rest of POE. They
781 should be spun off into a separate distribution for everyone to enjoy.
782
783 If StdinFilter and StdoutFilter seem backwards, remember that it's the
784 filters for the child process. StdinFilter is the one that dictates
785 what the child receives on STDIN. StdoutFilter tells the parent how to
786 parse the child's STDOUT.
787
789 Please see POE for more information about authors and contributors.
790
791
792
793perl v5.36.0 2022-07-22 POE::Wheel::Run(3)