NAME

GT::IPC::Run - Run programs or code in parallel


SYNOPSIS

    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";
        }
    }


DESCRIPTION

Module to simplify running a program or code reference in parallel. Allows catching and filtering the output of the program and filtering it.


FUNCTIONS

GT::IPC::Run will import one function run() if you request it to.

run

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.

First Argument

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.

Second Argument

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] });
Third Argument

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.

Forth Argument

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.


METHODS

new

The is a simple method that takes no arguments and returns a GT::IPC::Run object. It may take options in the future.

start

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:

program

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.

stdout

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.

stderr

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.

stdin

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.

reaper

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.

done_callback

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.

do_one_loop

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);

do_loop

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.

exit_code

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 ALSO

See perlipc, perlfunc/system, perlfunc/exec, perlfork, and the Win32::Process manpage.


MAINTAINER

Scott Beck


COPYRIGHT

Copyright (c) 2004 Gossamer Threads Inc. All Rights Reserved. http://www.gossamer-threads.com/


VERSION

Revision: $Id: Run.pm,v 1.22 2006/05/26 21:56:30 brewt Exp $