AnyEvent-Subprocess

 view release on metacpan or  search on metacpan

lib/AnyEvent/Subprocess.pm  view on Meta::CPAN

    # write to the child's stdin
    $run->delegate('stdin')->handle->push_write("Hello, world!\n");

    # close stdin after it has been written to the child
    $run->delegate('stdin')->handle->on_drain(sub { $_[0]->close_fh });

    # kill the child if it takes too long to produce a result
    my $killer = AnyEvent->timer( after => 42, interval => 0, cb => sub {
       $run->kill(2); # SIGINT.
    });

    # ensure the event loop runs until the on_completion handler dies
    EV::loop(); # you can use any AnyEvent-compatible event loop, including POE

    # eventually prints "The child said: Got line: Hello, world!", or
    # perhaps dies if your system is really really overloaded.

=head1 DESCRIPTION

There are so many possible ways to use this module that a tutorial
would take me months to write.  You should definitely read the test
suite to see what possibilities exist.  (There is also an examples
directory in the dist.)

The basic "flow" is like in the SYNOPSIS section; create a job, call
run, wait for your callback to be called with the exit status of the
subprocess.

The fun comes when you add delegates.

Delegates are technically instances of classes.  Typing:

   my $stdin = AnyEvent::Subprocess::Job::Delegate::Handle->new(
       name      => 'stdin',
       direction => 'w',
       replace   => \*STDIN,
   );

Every time you want to be able to write to STDIN is going to become
tiring after a while.  When you load C<AnyEvent::Subprocess>, you also
load
L<AnyEvent::Subprocess::DefaultDelegate|AnyEvent::Subprocess::DefaultDelegates>.
This registers short names for each delegate and will cause
C<AnyEvent::Subprocess::Job> to build the actual instances
automatically.  This means you can say C<'StandardHandles'> to get a
delegate for each of STDIN, STDOUT, and STDERR.  If you want to know
how all the sugary names work, just open C<DefaultDelegates.pm> and
take a look.  (The documentation for that module also covers that, as
well as how to define your own delegate builders.)

If you are too lazy to look -- there are delegates for giving the
child arbitrary sockets or pipes opened to arbitrary file descriptors
(so you can deal with more than stdin/stdout/stderr and communicate
bidirectionally between the parent and child), there is a delegate for
giving the child a pseudo-tty (which can run complicatged programs,
like emacs!), there is a delegate for capturing any input
automatically, and passing it back to the parent via the C<Done>
object, and there is a delegate for calling functions in the parent
when certain events are received.

Once you have decided what delegates your job needs, you need to
create a job object:

   my $proc = AnyEvent::Subprocess->new(
       delegates     => [qw/List them here/],
       code          => sub { code to run in the child },
       on_completion => sub { code to run in the parent when the child is done },
   );

Then you can run it:

   my $running = $proc->run;
   my $another = $proc->run({ with => 'args' }); # a separate process

The C<code> coderef receives a hashref as an argument; delegates
typically populate this for you, but you can also pass a hashref of
args to run (that will be merged with any arguments the delegates
create; the delegates' arguments "win" if there is a conflict).  The
code then runs in a child process until it stops running for some
reason.  The C<on_completion> hook is then run in the parent, with the
L<AnyEvent::Subprocess::Done|AnyEvent::Subprocess::Done> object passed
in as an argument.

You can, of course, have as many children running concurrently as you
desire.  The event loop handles managing the any IO with the child,
and the notifications of the child dying.  (You don't need to deal
with SIGCHLD or anything like that.)

=head1 OVERVIEW

C<AnyEvent::Subprocess> is a set of modules for running external
processes, and interacting with them in the context of an event-driven
program.  It is similar to L<POE::Wheel::Run|POE::Wheel::Run>, but
much more customizable (and Moose-based).  It is also similar to
modules that really want to be event-based, but aren't for some
reason; this includes L<IPC::Run|IPC::Run> and
L<IPC::Open3|IPC::Open3>, L<Expect|Expect>, and even the built-in
C<qx//> operator.  You can replace all those modules with this one,
and have the ability to write much more flexible applications and
libraries.

AnyEvent::Subprocess is based on three classes;
C<AnyEvent::Subprocess::Job>, which represents a job that can be run
at a later time, C<AnyEvent::Subprocess::Running>, which represents a
running child process, and C<AnyEvent::Subprocess::Done>, which
represents a completed job.  The C<Job> object contains the command to
run, information about its environment (which handles to capture,
which plugins to run, what to do when the job is done, etc.).  Then
C<Run> object is returned by C<< $job->run >>, and lets you interact
with the running subprocess.  This includes things like writing to its
pipes/sockets, reading from its pipes, sending it signals, and so on.
When the running job exits, the C<on_completion> handler provided by
the Job object is called with a C<Done> object.  This contains the
exit status, output that the process produced (if requested), and so
on.

What makes this more interesting is the ability to add delegates to
any of these classes.  These delegates are called into at various
points and allow you to add more features.  By default, you just get a
callback when the process exits.  You can also kill the running
process.  That's it.  From there, you can add delegates to add more



( run in 0.858 second using v1.01-cache-2.11-cpan-39bf76dae61 )