GT::IPC::Run - Run programs or code in parallel
use GT::IPC::Run;
# stderr and stdout filters default to a # GT::IPC::Line::Filter my $exit_code = run '/bin/ls', # Program to run \*stdout_handle, # stdout event \&stderr_handler, # stderr event \$stdin; # stdin
my $io = new GT::IPC::Run;
use GT::IPC::Filter::Line;
my $pid = $io->start( stdout => GT::IPC::Filter::Line->new( regex => "\r?\n", output => sub { print "Output: $_[0]\n" } ), program => sub { print "I got forked\n" }, );
while ($io->do_one_loop) { if (defined(my $exit = $io->exit_code($pid))) { print "$pid exited ", ($exit>>8), "\n"; } }
Module to simplify running a program or code reference in parallel. Allows catching and filtering the output of the program and filtering it.
GT::IPC::Run will import one function run()
if you request it to.
Run is a simple interface to running a program or a subroutine in a separate process and catching the output, both stderr and stdout. This function takes four arguments, only the first argument is required.
The first argument to run()
is the program to run or the code reference to
run. This argument can be one of three things.
If a code reference if passed as the first argument to run()
, GT::IPC::Run
will fork off and run the code reference. You SHOULD NOT exit in the code
reference if you want your code to work on Windows. Calling die()
is ok,
as your code is evaled. There are some things you CAN NOT do if you want your
code to work on Windows.
You SHOULD NOT make any calles to system()
or exec()
. For some reason, on
Windows, this breaks filehandle inheritance so all your output from that moment
on (including the system()
or exec()
) call will go to the real output
channel, STDERR or STDOUT.
You SHOULD NOT change STDERR or STDOUT. The child process on Windows can
affect the filehandles in the parent. This is probably because of the way
fork()
on Windows is emulated as threads.
You probably should not fork()
either, though this is not confirmed I
really doubt it will work the way you plan.
If an array reference is passed in it will be dereferenced and passed to
exec()
. If a scalar is passed in it will be passed to exec()
.
On Windows the arguments are passed to Win32::Process::Create as the program you wish to run. See the Win32::Process::Create manpage.
The second argument to run()
is what you want to happen to STDOUT as it
comes in. This argument can be one of three things.
If it is a reference to a GT::IPC::Filter:: class, that will be used to call your code. See the GT::IPC::Filter manpage for details.
If it is a code reference, a new GT::IPC::Filter::Line object will be created and your code reference will be passed in. Exactly:
$out = GT::IPC::Filter::Line->new($out);
GT::IPC::Filter::Line will call your code reference for each line of output from the program, the end of the line will be stripped. See the GT::IPC::Filter::Line manpage for details.
If the argument is a scalar reference, again, a new GT::IPC::Filter::Line object will be created. Exactly:
$out = GT::IPC::Filter::Line->new(sub { $$out .= $_[0] });
The third argument to run() is used to handle STDERR if and when what you are running produces it.
This can be the exact same thing as the second argument, but will work on STDERR.
This argument is how to handle STDIN. It may be one of two things.
If it is a SCALAR, it will be printed to the input of what you are running.
The is a simple method that takes no arguments and returns a GT::IPC::Run object. It may take options in the future.
This is the more complex method to start a program running. When you call this
method, the program you specify is started right away and it's PID (process ID)
is returned to you. After you call this you will either need to call
do_loop()
or do_one_loop()
to start getting the programs or code
references output. See do_loop and do_one_loop else where in this
document.
This method takes a hash of arguments. The arguments are:
The name of the program, or code reference you wish to run. This is treated the same way as the first argument to run(). See run else where in this document for a description of how this argument is treated.
This is how you want STDOUT treated. It can be the same things as the second argument to run(). See run else where in this document for a description of how this argument is treated.
This is how you want STDERR treated. It can be the same things as the third argument to run(). See run else where in this document for a description of how this argument is treated.
This argument is how to handle STDIN. It may be one of two things. It is treated like the forth argument to run(). See run else where in this document for a description of how this argument is treated.
This is a code reference that will be ran once a process has exited. Note: the process may not be done sending us STDOUT or STDERR when it exits.
The code reference is called with the pid as it's first argument and the exit
status of the program for its second argument. The exit status is the same as
it is returned by waitpid(). The exit status is somewhat fiddled on Windows to
act the way you want it to, e.g. $exit_status >> 8
will be the
number the program exited with.
This is a code reference that works similarly to reaper except that it is only called after the child has died AND all STDOUT/STDERR output has been sent, unlike reaper which is called on exit, regardless of any output that may still be pending.
The code reference is called wih the pid and exit status of the program as its two arguments.
This method takes one argument, the time to wait for select()
to return
something in milliseconds. This does one select loop on all the processes. You
will need to called this after you call start()
. Typically:
my $ipc = new GT::IPC::Run; my $pid = $ipc->start(program => 'ls'); 1 while $ipc->do_one_loop; my $exit_status = $ipc->exit_code($pid);
This is similar to do_one_loop
, except it does not return unless all
processes are finished. Almost the same as:
1 while $ipc->do_one_loop;
You can pass the wait time to do_loop()
and it will be passed on to
do_one_loop
. The wait time is in milliseconds.
This method takes a pid as an argument and returns the exit status of that processes pid. If the process has not exited yet or GT::IPC::Run did not launch the process, returns undefined. The exit code returned by this is the same as returned by waitpid. See perlfunc/waitpid and perlfunc/system.
See perlipc, perlfunc/system, perlfunc/exec, perlfork, and the Win32::Process manpage.
Scott Beck
Copyright (c) 2004 Gossamer Threads Inc. All Rights Reserved. http://www.gossamer-threads.com/
Revision: $Id: Run.pm,v 1.22 2006/05/26 21:56:30 brewt Exp $