Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
POE::Wheel::Run(3)    User Contributed Perl Documentation   POE::Wheel::Run(3)

NAME
       POE::Wheel::Run - portably run blocking code and	programs in
       subprocesses

SYNOPSIS
	 #!/usr/bin/perl

	 use warnings;
	 use strict;

	 use POE qw( Wheel::Run	);

	 POE::Session->create(
	   inline_states => {
	     _start	      => \&on_start,
	     got_child_stdout => \&on_child_stdout,
	     got_child_stderr => \&on_child_stderr,
	     got_child_close  => \&on_child_close,
	     got_child_signal => \&on_child_signal,
	   }
	 );

	 POE::Kernel->run();
	 exit 0;

	 sub on_start {
	   my $child = POE::Wheel::Run->new(
	     Program =>	[ "/bin/ls", "-1", "/" ],
	     StdoutEvent  => "got_child_stdout",
	     StderrEvent  => "got_child_stderr",
	     CloseEvent	  => "got_child_close",
	   );

	   $_[KERNEL]->sig_child($child->PID, "got_child_signal");

	   # Wheel events include the wheel's ID.
	   $_[HEAP]{children_by_wid}{$child->ID} = $child;

	   # Signal events include the process ID.
	   $_[HEAP]{children_by_pid}{$child->PID} = $child;

	   print(
	     "Child pid	", $child->PID,
	     " started as wheel	", $child->ID, ".\n"
	   );
	 }

	 # Wheel event,	including the wheel's ID.
	 sub on_child_stdout {
	   my ($stdout_line, $wheel_id)	= @_[ARG0, ARG1];
	   my $child = $_[HEAP]{children_by_wid}{$wheel_id};
	   print "pid ", $child->PID, "	STDOUT:	$stdout_line\n";
	 }

	 # Wheel event,	including the wheel's ID.
	 sub on_child_stderr {
	   my ($stderr_line, $wheel_id)	= @_[ARG0, ARG1];
	   my $child = $_[HEAP]{children_by_wid}{$wheel_id};
	   print "pid ", $child->PID, "	STDERR:	$stderr_line\n";
	 }

	 # Wheel event,	including the wheel's ID.
	 sub on_child_close {
	   my $wheel_id	= $_[ARG0];
	   my $child = delete $_[HEAP]{children_by_wid}{$wheel_id};

	   # May have been reaped by on_child_signal().
	   unless (defined $child) {
	     print "wid	$wheel_id closed all pipes.\n";
	     return;
	   }

	   print "pid ", $child->PID, "	closed all pipes.\n";
	   delete $_[HEAP]{children_by_pid}{$child->PID};
	 }

	 sub on_child_signal {
	   print "pid $_[ARG1] exited with status $_[ARG2].\n";
	   my $child = delete $_[HEAP]{children_by_pid}{$_[ARG1]};

	   # May have been reaped by on_child_close().
	   return unless defined $child;

	   delete $_[HEAP]{children_by_wid}{$child->ID};
	 }

DESCRIPTION
       POE::Wheel::Run executes	a program or block of code in a	subprocess,
       created the usual way: using fork().  The parent	process	may exchange
       information with	the child over the child's STDIN, STDOUT and STDERR
       filehandles.

       In the parent process, the POE::Wheel::Run object represents the	child
       process.	 It has	methods	such as	PID() and kill() to query and manage
       the child process.

       POE::Wheel::Run's put() method sends data to the	child's	STDIN.	Child
       output on STDOUT	and STDERR may be dispatched as	events within the
       parent, if requested.

       POE::Wheel::Run can also	notify the parent when the child has closed
       its output filehandles.	Some programs remain active, but they close
       their output filehandles	to indicate they are done writing.

       A more reliable way to detect child exit	is to use POE::Kernel's
       sig_child() method to wait for the wheel's process to be	reaped.	 It is
       in fact vital to	use sig_child()	in all circumstances since without it,
       POE will	not try	to reap	child processes.

       Failing to use sig_child() has in the past led to wedged	machines.
       Long-running programs have leaked processes, eventually consuming all
       available slots in the process table and	requiring reboots.

       Because process leaks are so severe, POE::Kernel	will check for this
       condition on exit and display a notice if it finds that processes are
       leaking.	 Developers should heed	these warnings.

       POE::Wheel::Run communicates with the child process in a	line-based
       fashion by default.  Programs may override this by specifying some
       other POE::Filter object	in "StdinFilter", "StdoutFilter",
       "StdioFilter" and/or "StderrFilter".

PUBLIC METHODS
   Constructor
       POE::Wheel subclasses tend to perform a lot of setup so that they run
       lighter and faster.  POE::Wheel::Run's constructor is no	exception.

       new

       new() creates and returns a new POE::Wheel::Run object.	If it's
       successful, the object will represent a child process with certain
       specified qualities.  It	also provides an OO- and event-based interface
       for asynchronously interacting with the process.

       Conduit

       Conduit specifies the inter-process communications mechanism that will
       be used to pass data between the	parent and child process.  Conduit may
       be one of "pipe", "socketpair", "inet", "pty", or "pty-pipe".
       POE::Wheel::Run will use	the most appropriate Conduit for the run-time
       (not the	compile-time) operating	system,	but this varies	from one OS to
       the next.

       Internally, POE::Wheel::Run passes the Conduit type to
       POE::Pipe::OneWay and POE::Pipe::TwoWay.	 These helper classes were
       created to make IPC portable and	reusable.  They	do not require the
       rest of POE.

       Three Conduit types use pipes or	pipelike inter-process communication:
       "pipe", "socketpair" and	"inet".	 They determine	whether	the internal
       IPC uses	pipe(),	socketpair() or	Internet sockets.  These Conduit
       values are passed through to POE::Pipe::OneWay or POE::Pipe::TwoWay
       internally.

       The "pty" conduit type runs the child process under a pseudo-tty, which
       is created by IO::Pty.  Pseudo-ttys (ptys) convince child processes
       that they are interacting with terminals	rather than pipes.  This may
       be used to trick	programs like ssh into believing it's secure to	prompt
       for a password, although	passphraseless identities might	be better for
       that.

       The "pty" conduit cannot	separate STDERR	from STDOUT, but the "pty-
       pipe" mode can.

       The "pty-pipe" conduit uses a pty for STDIN and STDOUT and a one-way
       pipe for	STDERR.	 The additional	pipe keeps STDERR output separate from
       STDOUT.

       The IO::Pty module is only loaded if "pty" or "pty-pipe"	is used.  It's
       not a dependency	until it's actually needed.

       Winsize

       Winsize sets the	child process' terminal	size.  Its value should	be an
       arrayref	with four elements.  The first two elements must be the	number
       of lines	and columns for	the child's terminal window, respectively.
       The second pair of elements describe the	terminal's X and Y dimensions
       in pixels.  If the last pair is missing,	they will be calculated	from
       the lines and columns using a 9x16 cell size.

	 $_[HEAP]{child} = POE::Wheel::Run->new(
	   # ... among other things ...
	   Winsize => [	25, 80,	720, 400 ],
	 );

       Winsize is only valid for conduits that use pseudo-ttys:	"pty" and
       "pty-pipe".  Other conduits don't simulate terminals, so	they don't
       have window sizes.

       Winsize defaults	to the parent process' window size, assuming the
       parent process has a terminal to	query.

       CloseOnCall

       CloseOnCall, when true, turns on	close-on-exec emulation	for
       subprocesses that don't actually	call exec().  These would be instances
       when the	child is running a block of code rather	than executing an
       external	program.  For example:

	 $_[HEAP]{child} = POE::Wheel::Run->new(
	   # ... among other things ...
	   CloseOnCall => 1,
	   Program => \&some_function,
	 );

       CloseOnCall is off (0) by default.

       CloseOnCall works by closing all	file descriptors greater than $^F in
       the child process before	calling	the application's code.	 For more
       details,	please the discussion of $^F in	perlvar.

       StdioDriver

       StdioDriver specifies a single POE::Driver object to be used for	both
       STDIN and STDOUT.  It's equivalent to setting "StdinDriver" and
       "StdoutDriver" to the same POE::Driver object.

       POE::Wheel::Run will create and use a POE::Driver::SysRW	driver of one
       isn't specified.	 This is by far	the most common	use case, so it's the
       default.

       StdinDriver

       "StdinDriver" sets the POE::Driver used to write	to the child process'
       STDIN IPC conduit.  It is almost	never needed.  Omitting	it will	allow
       POE::Wheel::Run to use an internally created POE::Driver::SysRW object.

       StdoutDriver

       "StdoutDriver" sets the POE::Driver object that will be used to read
       from the	child process' STDOUT conduit.	It's almost never needed.  If
       omitted,	POE::Wheel::Run	will internally	create and use a
       POE::Driver::SysRW object.

       StderrDriver

       "StderrDriver" sets the driver that will	be used	to read	from the child
       process'	STDERR conduit.	 As with "StdoutDriver", it's almost always
       preferable to let POE::Wheel::Run instantiate its own driver.

       CloseEvent

       CloseEvent contains the name of an event	that the wheel will emit when
       the child process closes	its last open output handle.  This is a
       consistent notification that the	child is done sending output.  Please
       note that it does not signal when the child process has exited.
       Programs	should use sig_child() to detect that.

       While it	is impossible for ErrorEvent or	StdoutEvent to happen after
       CloseEvent, there is no such guarantee for CHLD,	which may happen
       before or after CloseEvent.

       In addition to the usual	POE parameters,	each CloseEvent	comes with one
       of its own:

       "ARG0" contains the wheel's unique ID.  This can	be used	to keep
       several child processes separate	when they're managed by	the same
       session.

       A sample	close event handler:

	 sub close_state {
	   my ($heap, $wheel_id) = @_[HEAP, ARG0];

	   my $child = delete $heap->{child}->{$wheel_id};
	   print "Child	", $child->PID,	" has finished.\n";
	 }

       ErrorEvent

       ErrorEvent contains the name of an event	to emit	if something fails.
       It is optional; if omitted, the wheel will not notify its session if
       any errors occur.  However, POE::Wheel::Run->new() will still throw an
       exception if it fails.

       "ARG0" contains the name	of the operation that failed.  It may be
       'read', 'write',	'fork',	'exec' or the name of some other function or
       task.  The actual values	aren't yet defined.  They will probably	not
       correspond so neatly to Perl builtin function names.

       "ARG1" and "ARG2" hold numeric and string values	for $!,	respectively.
       "$!" will eq "" for read	error 0	(child process closed the file
       handle).

       "ARG3" contains the wheel's unique ID.

       "ARG4" contains the name	of the child filehandle	that has the error.
       It may be "STDIN", "STDOUT", or "STDERR".  The sense of "ARG0" will be
       the opposite of what you	might normally expect for these	handles.  For
       example,	POE::Wheel::Run	will report a "read" error on "STDOUT" because
       it tried	to read	data from the child's STDOUT handle.

       A sample	error event handler:

	 sub error_state {
	   my ($operation, $errnum, $errstr, $wheel_id)	= @_[ARG0..ARG3];
	   $errstr = "remote end closed" if $operation eq "read" and !$errnum;
	   warn	"Wheel $wheel_id generated $operation error $errnum: $errstr\n";
	 }

       Note that unless	you deactivate the signal pipe,	you might also see
       "EIO" (5) error during read operations.

       StdinEvent

       StdinEvent contains the name of an event	that Wheel::Run	emits whenever
       everything queued by its	put() method has been flushed to the child's
       STDIN handle.  It is the	equivalent to POE::Wheel::ReadWrite's
       FlushedEvent.

       StdinEvent comes	with only one additional parameter: "ARG0" contains
       the unique ID for the wheel that	sent the event.

       StdoutEvent

       StdoutEvent contains the	name of	an event  that Wheel::Run emits
       whenever	the child process writes something to its STDOUT filehandle.
       In other	words, whatever	the child prints to STDOUT, the	parent
       receives	a StdoutEvent---provided that the child	prints something
       compatible with the parent's StdoutFilter.

       StdoutEvent comes with two parameters.  "ARG0" contains the information
       that the	child wrote to STDOUT.	"ARG1" holds the unique	ID of the
       wheel that read the output.

	 sub stdout_state {
	   my ($heap, $input, $wheel_id) = @_[HEAP, ARG0, ARG1];
	   print "Child	process	in wheel $wheel_id wrote to STDOUT: $input\n";
	 }

       StderrEvent

       StderrEvent behaves exactly as StdoutEvent, except for data the child
       process writes to its STDERR filehandle.

       StderrEvent comes with two parameters.  "ARG0" contains the information
       that the	child wrote to STDERR.	"ARG1" holds the unique	ID of the
       wheel that read the output.

	 sub stderr_state {
	   my ($heap, $input, $wheel_id) = @_[HEAP, ARG0, ARG1];
	   print "Child	process	in wheel $wheel_id wrote to STDERR: $input\n";
	 }

       RedirectStdout

       This is a filehandle or filename	to which standard output will be
       redirected.  It is an error to use this option together with
       StdoutEvent. This is useful in case your	program	needs to have standard
       I/O, but	do not actually	care for its contents to be visible to the
       parent.

       RedirectStderr

       Just like RedirectStdout, but with standard error. It is	an error to
       use this	together with StderrEvent

       RedirectStdin

       This is a filehandle or filename	which the child	process	will use as
       its standard input. It is an error to use this option with StdinEvent

       RedirectOutput

       This will redirect stderr and stdout to the same	filehandle. This is
       equivalent to do	doing something	like

	 $ something > /path/to/output 2>&1

       in bourne shell.

       NoStdin

       While output filehandles	will be	closed if there	are no events to be
       received	on them, stdin is open by default - because lack of an event
       handler does not	necessarily mean there is no desired input stream.
       This option explicitly disables the creation of an IPC stdin conduit.

       StdioFilter

       StdioFilter, if used, must contain an instance of a POE::Filter
       subclass.  This filter describes	how the	parent will format put() data
       for the child's STDIN, and how the parent will parse the	child's
       STDOUT.

       If STDERR will also be parsed, then a separate StderrFilter will	also
       be needed.

       StdioFilter defaults to a POE::Filter::Line instance, but only if both
       StdinFilter and StdoutFilter are	not specified.	If either StdinFilter
       or StdoutFilter is used,	then StdioFilter is illegal.

       StdinFilter

       StdinFilter may be used to specify a particular STDIN serializer	that
       is different from the STDOUT parser.  If	specified, it conflicts	with
       StdioFilter.  StdinFilter's value, if specified,	must be	an instance of
       a POE::Filter subclass.

       Without a StdinEvent, StdinFilter is illegal.

       StdoutFilter

       StdoutFilter may	be used	to specify a particular	STDOUT parser that is
       different from the STDIN	serializer.  If	specified, it conflicts	with
       StdioFilter.  StdoutFilter's value, if specified, must be an instance
       of a POE::Filter	subclass.

       Without a StdoutEvent, StdoutFilter is illegal.

       StderrFilter

       StderrFilter may	be used	to specify a filter for	a child	process'
       STDERR output.  If omitted, POE::Wheel::Run will	create and use its own
       POE::Filter::Line instance, but only if a StderrEvent is	specified.

       Without a StderrEvent, StderrFilter is illegal.

       Group

       Group contains a	numeric	group ID that the child	process	should run
       within.	By default, the	child process will run in the same group as
       the parent.

       Group is	not fully portable.  It	may not	work on	systems	that have no
       concept of user groups.	Also, the parent process may need to run with
       elevated	privileges for the child to be able to change groups.

       User

       User contains a numeric user ID that should own the child process.  By
       default,	the child process will run as the same user as the parent.

       User is not fully portable.  It may not work on systems that have no
       concept of users.  Also,	the parent process may need to run with
       elevated	privileges for the child to be able to change users.

       NoSetSid

       When true, NoSetSid disables setsid() in	the child process.  By
       default,	the child process calls	setsid() is called so that it may
       execute in a separate UNIX session.

       NoSetPgrp

       When true, NoSetPgrp disables setprgp() in the child process. By
       default,	the child process calls	setpgrp() to change its	process	group,
       if the OS supports that.

       setsid()	is used	instead	of setpgrp() if	Conduit	is pty or pty-pipe.
       See "NoSetSid".

       Priority

       Priority	adjusts	the child process' niceness or priority	level,
       depending on which (if any) the underlying OS supports.	Priority
       contains	a numeric offset which will be added to	the parent's priority
       to determine the	child's.

       The priority offset may be negative, which in UNIX represents a higher
       priority.  However UNIX requires	elevated privileges to increase	a
       process'	priority.

       Program

       Program specifies the program to	exec() or the block of code to run in
       the child process.  Program's type is significant.

       If Program holds	a scalar, its value will be executed as
       exec($program).	Shell metacharacters are significant, per exec(SCALAR)
       semantics.

       If Program holds	an array reference, it will executed as
       exec(@$program).	 As per	exec(ARRAY), shell metacharacters will not be
       significant.

       If Program holds	a code reference, that code will be called in the
       child process.  This mode allows	POE::Wheel::Run	to execute long-
       running internal	code asynchronously, while the usual modes execute
       external	programs.  The child process will exit after that code is
       finished, in such a way as to avoid DESTROY and END block execution.
       See "Coderef Execution Side Effects" for	more details.

       perlfunc	has more information about exec() and the different ways to
       call it.

       Please avoid calling exit() explicitly when executing a subroutine.
       The child process inherits all objects from the parent, including ones
       that may	perform	side effects.  POE::Wheel::Run takes special care to
       avoid object destructors	and END	blocks in the child process, but
       calling exit() will trigger them.

       ProgramArgs

       If specified, ProgramArgs should	refer to a list	of parameters for the
       program being run.

	 my @parameters	= qw(foo bar baz);  # will be passed to	Program
	 ProgramArgs =>	\@parameters;

   event EVENT_TYPE => EVENT_NAME, ...
       event() allows programs to change the events that Wheel::Run emits when
       certain activities occurs.  EVENT_TYPE may be one of the	event
       parameters described in POE::Wheel::Run's constructor.

       This example changes the	events that $wheel emits for STDIN flushing
       and STDOUT activity:

	 $wheel->event(
	   StdinEvent  => 'new-stdin-event',
	   StdoutEvent => 'new-stdout-event',
	 );

       Undefined EVENT_NAMEs disable events.

   put RECORDS
       put() queues up a list of RECORDS that will be sent to the child
       process'	STDIN filehandle.  These records will first be serialized
       according to the	wheel's	StdinFilter.  The serialized RECORDS will be
       flushed asynchronously once the current event handler returns.

   get_stdin_filter
       get_stind_filter() returns the POE::Filter object currently being used
       to serialize put() records for the child's STDIN	filehandle.  The
       return object may be used according to its own interface.

   get_stdout_filter
       get_stdout_filter() returns the POE::Filter object currently being used
       to parse	what the child process writes to STDOUT.

   get_stderr_filter
       get_stderr_filter() returns the POE::Filter object currently being used
       to parse	what the child process writes to STDERR.

   set_stdio_filter FILTER_OBJECT
       Set StdinFilter and StdoutFilter	to the same new	FILTER_OBJECT.
       Unparsed	STDOUT data will be parsed later by the	new FILTER_OBJECT.
       However,	data already put() will	remain serialized by the old filter.

   set_stdin_filter FILTER_OBJECT
       Set StdinFilter to a new	FILTER_OBJECT.	Data already put() will	remain
       serialized by the old filter.

   set_stdout_filter FILTER_OBJECT
       Set StdoutFilter	to a new FILTER_OBJECT.	 Unparsed STDOUT data will be
       parsed later by the new FILTER_OBJECT.

   set_stderr_filter FILTER_OBJECT
       Set StderrFilter	to a new FILTER_OBJECT.	 Unparsed STDERR data will be
       parsed later by the new FILTER_OBJECT.

   pause_stdout
       Pause reading of	STDOUT from the	child.	The child process may block if
       the STDOUT IPC conduit fills up.	 Reading may be	resumed	with
       resume_stdout().

   pause_stderr
       Pause reading of	STDERR from the	child.	The child process may block if
       the STDERR IPC conduit fills up.	 Reading may be	resumed	with
       resume_stderr().

   resume_stdout
       Resume reading from the child's STDOUT filehandle.  This	is only
       meaningful if pause_stdout() has	been called and	remains	in effect.

   resume_stderr
       Resume reading from the child's STDERR filehandle.  This	is only
       meaningful if pause_stderr() has	been called and	remains	in effect.

   shutdown_stdin
       shutdown_stdin()	closes the child process' STDIN	and stops the wheel
       from reporting StdinEvent.  It is extremely useful for running
       utilities that expect to	receive	EOF on STDIN before they respond.

   ID
       ID() returns the	wheel's	unique ID.  Every event	generated by a
       POE::Wheel::Run object includes a wheel ID so that it can be matched to
       the wheel that emitted it.  This	lets a single session manage several
       wheels without becoming confused	about which one	generated what event.

       ID() is not the same as PID().

   PID
       PID() returns the process ID for	the child represented by the
       POE::Wheel::Run object.	It's often used	as a parameter to sig_child().

       PID() is	not the	same as	ID().

   kill	SIGNAL
       POE::Wheel::Run's kill()	method sends a SIGNAL to the child process the
       object represents.  kill() is often used	to force a reluctant program
       to terminate.  SIGNAL is	one of the operating signal names present in
       %SIG.

       kill() returns the number of processes successfully signaled: 1 on
       success,	or 0 on	failure, since the POE::Wheel::Run object only affects
       at most a single	process.

       kill() sends SIGTERM if SIGNAL is undef or omitted.

   get_driver_out_messages
       get_driver_out_messages() returns the number of put() records remaining
       in whole	or in part in POE::Wheel::Run's	POE::Driver output queue.  It
       is often	used to	tell whether the wheel has more	input for the child
       process.

       In most cases, StdinEvent may be	used to	trigger	activity when all data
       has been	sent to	the child process.

   get_driver_out_octets
       get_driver_out_octets() returns the number of serialized	octets
       remaining in POE::Wheel::Run's POE::Driver output queue.	 It is often
       used to tell whether the	wheel has more input for the child process.

TIPS AND TRICKS
   MSWin32 Support
       In the past POE::Wheel::Run did not support MSWin32 and users had to
       use custom work-arounds.	Then Chris Williams ( BINGOS ) arrived and
       saved the day with his POE::Wheel::Run::Win32 module. After some
       testing,	it was decided to merge	the win32 code into POE::Wheel::Run.
       Everyone	was happy!

       However,	after some investigation Apocalypse ( APOCAL ) found out that
       in some situations it still didn't behave properly. The root cause was
       that the	win32 code path	in POE::Wheel::Run didn't exit cleanly.	This
       means DESTROY and END blocks got	executed! After	talking	with more
       people, the solution was	not pretty.

       The problem is that there is no equivalent of POSIX::_exit() for
       MSWin32.	 Hopefully, in a future	version	of Perl	this can be fixed! In
       the meantime, POE::Wheel::Run will use CORE::kill() to terminate	the
       child. However, this comes with a caveat: you will leak around 1KB per
       exec. The code has been improved	so the chance of this happening	has
       been reduced.

       As of now the most reliable way to trigger this is to exec an invalid
       binary. The definition of "invalid binary" depends on different things,
       but what	it means is that Win32::Job->spawn() failed to run. This will
       force POE::Wheel::Run to	use the	workaround to exit the child. If this
       happens,	a very big warning will	be printed to the STDERR of the	child
       and the parent process will receive it.

       If you are a Perl MSWin32 hacker, PLEASE	help us	with this situation!
       Go read rt.cpan.org bug #56417 and talk with us/p5p to see where	you
       can contribute.

       Thanks again for	your patience as we continue to	improve
       POE::Wheel::Run on MSWin32!

       kill() and ClosedEvent on Windows

       Windows will often fail to report EOF on	pipes when subprocesses	are
       killed.	The work-around	is to catch the	signal in the subprocess, and
       exit normally:

	 my $child = POE::Wheel::Run->new(
	   Program => sub {
	     $SIG{INT} = sub { exit };
	     ...;
	   },
	   ...,
	 );

       Be sure to kill() the subprocess	using the same signal that it catches
       and exits upon.	Remember, not all signals can be caught	by user	code.

	 $child->kill("INT");

   Execution Environment
       It's common to scrub a child process' environment, so that only
       required, secure	values exist.  This amounts to clearing	the contents
       of %ENV and repopulating	it.

       Environment scrubbing is	easy when the child process is running a
       subroutine, but it's not	so easy---or at	least not as intuitive---when
       executing external programs.

       The way we do it	is to run a small subroutine in	the child process that
       performs	the exec() call	for us.

	 Program => \&exec_with_scrubbed_env,

	 sub exec_with_scrubbed_env {
	   delete @ENV{keys @ENV};
	   $ENV{PATH} =	"/bin";
	   exec(@program_and_args);
	 }

       That deletes everything from the	environment and	sets a simple, secure
       PATH before executing a program.

   Coderef Execution Side Effects
       The child process is created by fork(), which duplicates	the parent
       process including a copy	of POE::Kernel,	all running Session instances,
       events in the queue, watchers, open filehandles,	and so on.

       When executing an external program, the UNIX exec() call	immediately
       replaces	the copy of the	parent with a completely new program.

       When executing internal coderefs, however, we must preserve the code
       and any memory it might reference.  This	leads to some potential	side
       effects.

       DESTROY and END Blocks Run Twice

       Objects that were created in the	parent process are copied into the
       child.  When the	child exits normally, any DESTROY and END blocks are
       executed	there.	Later, when the	parent exits, they may run again.

       POE::Wheel::Run takes steps to avoid running DESTROY and	END blocks in
       the child process.  It uses POSIX::_exit() to bypass them.  If that
       fails, it may even kill() itself.

       If an application needs to exit explicitly, for example to return an
       error code to the parent	process, then please use POSIX::_exit()	rather
       than Perl's core	exit().

       POE::Kernel's run() method was never called

       This warning is displayed from POE::Kernel's DESTROY method.  It's a
       side effect of calling exit() in	a child	process	that was started
       before "POE::Kernel->run()" could be called.  The child process
       receives	a copy of POE::Kernel where run() wasn't called, even if it
       was called later	in the parent process.

       The most	direct solution	is to call POSIX::_exit() rather than exit().
       This will bypass	POE::Kernel's DESTROY, and the message it emits.

       Running POE::Kernel in the Child

       Calling "POE::Kernel->run()" in the child process effectively resumes
       the copy	of the parent process.	This is	rarely (if ever) desired.

       More commonly, an application wants to run an entirely new POE::Kernel
       instance	in the child process.  This is supported by first stop()ping
       the copied instance, starting one or more new sessions, and calling
       run() again.  For example:

	 Program => sub	{
	   # Wipe the existing POE::Kernel clean.
	   $poe_kernel->stop();

	   # Start a new session, or more.
	   POE::Session->create(
	     ...
	   );

	   # Run the new sessions.
	   POE::Kernel->run();
	 }

       Strange things are bound	to happen if the program does not call "stop"
       in POE::Kernel before "run" in POE::Kernel.  However this is vaguely
       supported in case it's the right	thing to do at the time.

SEE ALSO
       POE::Wheel describes wheels in general.

       The SEE ALSO section in POE contains a table of contents	covering the
       entire POE distribution.

CAVEATS	& TODOS
       POE::Wheel::Run's constructor should emit proper	events when it fails.
       Instead,	it just	dies, carps or croaks.	This isn't necessarily bad; a
       program can trap	the death in new() and move on.

       Priority	is a delta, not	an absolute niceness value.

       It might	be nice	to specify User	by name	rather than just UID.

       It might	be nice	to specify Group by name rather	than just GID.

       POE::Pipe::OneWay and Two::Way don't require the	rest of	POE.  They
       should be spun off into a separate distribution for everyone to enjoy.

       If StdinFilter and StdoutFilter seem backwards, remember	that it's the
       filters for the child process.  StdinFilter is the one that dictates
       what the	child receives on STDIN.  StdoutFilter tells the parent	how to
       parse the child's STDOUT.

AUTHORS	& COPYRIGHTS
       Please see POE for more information about authors and contributors.

perl v5.32.0			  2020-02-01		    POE::Wheel::Run(3)

NAME | SYNOPSIS | DESCRIPTION | PUBLIC METHODS | TIPS AND TRICKS | SEE ALSO | CAVEATS & TODOS | AUTHORS & COPYRIGHTS

Want to link to this manual page? Use this URL:
<https://www.freebsd.org/cgi/man.cgi?query=POE::Wheel::Run&sektion=3&manpath=FreeBSD+12.2-RELEASE+and+Ports>

home | help