NAME¶
"IO::Async::ChildManager" - facilitates the execution of child
processes
SYNOPSIS¶
This object is used indirectly via an "IO::Async::Loop":
use IO::Async::Loop;
use POSIX qw( WEXITSTATUS );
my $loop = IO::Async::Loop->new;
...
$loop->run_child(
command => "/bin/ps",
on_finish => sub {
my ( $pid, $exitcode, $stdout, $stderr ) = @_;
my $status = WEXITSTATUS( $exitcode );
print "ps [PID $pid] exited with status $status\n";
},
);
$loop->open_child(
command => [ "/bin/ping", "-c4", "some.host" ],
stdout => {
on_read => sub {
my ( $stream, $buffref, $eof ) = @_;
while( $$buffref =~ s/^(.*)\n// ) {
print "PING wrote: $1\n";
}
return 0;
},
},
on_finish => sub {
my ( $pid, $exitcode ) = @_;
my $status = WEXITSTATUS( $exitcode );
...
},
);
my ( $pipeRd, $pipeWr ) = IO::Async::OS->pipepair;
$loop->spawn_child(
command => "/usr/bin/my-command",
setup => [
stdin => [ "open", "<", "/dev/null" ],
stdout => $pipeWr,
stderr => [ "open", ">>", "/var/log/mycmd.log" ],
chdir => "/",
]
on_exit => sub {
my ( $pid, $exitcode ) = @_;
my $status = WEXITSTATUS( $exitcode );
print "Command exited with status $status\n";
},
);
$loop->spawn_child(
code => sub {
do_something; # executes in a child process
return 1;
},
on_exit => sub {
my ( $pid, $exitcode, $dollarbang, $dollarat ) = @_;
my $status = WEXITSTATUS( $exitcode );
print "Child process exited with status $status\n";
print " OS error was $dollarbang, exception was $dollarat\n";
},
);
DESCRIPTION¶
This module extends the functionality of the containing
"IO::Async::Loop" to manage the execution of child processes. It
acts as a central point to store PID values of currently-running children, and
to call the appropriate continuation handler code when the process terminates.
It provides useful wrapper methods that set up filehandles and other child
process details, and to capture the child process's STDOUT and STDERR streams.
METHODS¶
When active, the following methods are available on the containing
"Loop" object.
$pid = $loop->spawn_child( %params )¶
This method creates a new child process to run a given code block or command.
The %params hash takes the following keys:
- command => ARRAY or STRING
- Either a reference to an array containing the command and
its arguments, or a plain string containing the command. This value is
passed into perl's "exec" function.
- code => CODE
- A block of code to execute in the child process. It will be
called in scalar context inside an "eval" block.
- setup => ARRAY
- A reference to an array which gives file descriptors to set
up in the child process before running the code or command. See
below.
- on_exit => CODE
- A continuation to be called when the child processes exits.
It will be invoked in the following way:
$on_exit->( $pid, $exitcode, $dollarbang, $dollarat )
The second argument is passed the plain perl $? value. To use that usefully,
see "WEXITSTATUS" and others from "POSIX".
Exactly one of the "command" or "code" keys must be
specified.
If the "command" key is used, the given array or string is executed
using the "exec" function.
If the "code" key is used, the return value will be used as the
exit(2) code from the child if it returns (or 255 if it returned
"undef" or thows an exception).
Case | WEXITSTATUS($exitcode) | $dollarbang | $dollarat
--------------+------------------------+-------------+----------
exec succeeds | exit code from program | 0 | ""
exec fails | 255 | $! | ""
$code returns | return value | $! | ""
$code dies | 255 | $! | $@
It is usually more convenient to use the "open_child" method in simple
cases where an external program is being started in order to interact with it
via file IO, or even "run_child" when only the final result is
required, rather than interaction while it is running.
"setup" array¶
This array gives a list of file descriptor operations to perform in the child
process after it has been
fork(2)ed from the parent, before running the code
or command. It consists of name/value pairs which are ordered; the operations
are performed in the order given.
- fdn => ARRAY
- Gives an operation on file descriptor n. The first
element of the array defines the operation to be performed:
- [ 'close' ]
- The file descriptor will be closed.
- [ 'dup', $io ]
- The file descriptor will be dup2(2)ed from the given IO
handle.
- [ 'open', $mode, $file ]
- The file descriptor will be opened from the named file in
the given mode. The $mode string should be in the form usually given to
the "open" function; such as '<' or '>>'.
- [ 'keep' ]
- The file descriptor will not be closed; it will be left
as-is.
A non-reference value may be passed as a shortcut, where it would contain the
name of the operation with no arguments (i.e. for the "close" and
"keep" operations).
- IO => ARRAY
- Shortcut for passing "fdn", where n
is the fileno of the IO reference. In this case, the key must be a
reference that implements the "fileno" method. This is mostly
useful for
$handle => 'keep'
- fdn => IO
- A shortcut for the "dup" case given above.
- stdin => ...
- stdout => ...
- stderr => ...
- Shortcuts for "fd0", "fd1" and
"fd2" respectively.
- env => HASH
- A reference to a hash to set as the child process's
environment.
- nice => INT
- Change the child process's scheduling priority using
"POSIX::nice".
- chdir => STRING
- Change the child process's working directory using
"chdir".
- setuid => INT
- setgid => INT
- Change the child process's effective UID or GID.
- setgroups => ARRAY
- Change the child process's groups list, to those groups
whose numbers are given in the ARRAY reference.
On most systems, only the privileged superuser change user or group IDs.
"IO::Async" will NOT check before detaching the child
process whether this is the case.
If setting both the primary GID and the supplementary groups list, it is
suggested to set the primary GID first. Moreover, some operating systems
may require that the supplementary groups list contains the primary
GID.
If no directions for what to do with "stdin", "stdout" and
"stderr" are given, a default of "keep" is implied. All
other file descriptors will be closed, unless a "keep" operation is
given for them.
If "setuid" is used, be sure to place it after any other operations
that might require superuser privileges, such as "setgid" or opening
special files.
AUTHOR¶
Paul Evans <leonerd@leonerd.org.uk>