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

FreeBSD Manual Pages

  
 
  

home | help
AnyEvent::Subprocess(3User Contributed Perl DocumentatiAnyEvent::Subprocess(3)

NAME
       AnyEvent::Subprocess - flexible,	OO, asynchronous process spawning and
       management

VERSION
       version 1.102912

SYNOPSIS
	   use AnyEvent::Subprocess;

	   # prepare the job
	   my $job = AnyEvent::Subprocess->new(
	       delegates     =>	['StandardHandles'],
	       on_completion =>	sub { die 'bad exit status' unless $_[0]->is_success },
	       code	     =>	sub {
		   my %args = %{$_[0]};
		   while(<>){
		       print "Got line:	$_";
		   }
		   exit	0;
	       },
	   );

	   # start the child
	   my $run = $job->run;

	   # add watcher to print the next line	we see on the child's stdout
	   $run->delegate('stdout')->handle->push_read(	line =>	sub {
	       my ($h, $line) =	@_;
	       say "The	child said: $line";
	   });

	   # 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.

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 "AnyEvent::Subprocess", you	also
       load AnyEvent::Subprocess::DefaultDelegate.  This registers short names
       for each	delegate and will cause	"AnyEvent::Subprocess::Job" to build
       the actual instances automatically.  This means you can say
       '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
       "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	"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 "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 "on_completion" hook is then run in	the parent, with the
       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.)

OVERVIEW
       "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 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 IPC::Run and
       IPC::Open3, Expect, and even the	built-in "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;
       "AnyEvent::Subprocess::Job", which represents a job that	can be run at
       a later time, "AnyEvent::Subprocess::Running", which represents a
       running child process, and "AnyEvent::Subprocess::Done",	which
       represents a completed job.  The	"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 "Run"
       object is returned by "$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 "on_completion" handler provided	by the
       Job object is called with a "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
       features.  You can add a	pipe to	share between the parent and the
       child.  Instead of sharing a pipe, you can have an fd opened to an
       arbitrary file descriptor number	in the child.  You have	an infinite
       number of these,	so you can capture the child's stdout and stderr,
       write to	its stdin, and also share a socket for out-of-band
       communication.  You can also open a pipe	to the child's fd #5 and write
       to it.  (This is	nice if	you are	invoking something like	"gpg" that
       wants the password written on an	arbitrary fd other than	1.)

       (This is	all done with the included "Handle" delegate.  See
       AnyEvent::Subprocess::Job::Delegate::Handle.)

       You can then build upon this; instead of	writing	your own code to
       reading the handles when	they become readable and accumulate input, you
       can write a delegate that saves all the data coming from	a given	handle
       and gives it to your program after the child exits (via the "Done"
       instance).

       (This is	also included via the "CaptureHandle" delegate.	 See
       AnyEvent::Subprocess::Job::Delegate::CaptureHandle.)

       All of this integrates into your	existing event-based app; waiting for
       IO from the child (or waiting for the child to exit) is asynchronous,
       and lets	your app do other work while waiting for the child.  (It can
       integrate nicely	into Coro, for example,	unlike the default "qx//".)

BUGS
       The parent's event loop still exists in the child process, which	means
       you can't safely	use it in the child.  I	have tried to work around this
       in a few	event loops; my	"AnyEventX::Cancel" module on github is	an
       early attempt.  When that becomes stable, I will	remove this
       restriction.

       In the mean time, YOU MUST NOT USE ANY EVENT-LOOP FUNCTIONS IN THE
       CHILD.

       This is not a problem if	you are	running	external processes, but	is a
       problem if you are running a code block and you want to do event-ful
       things in there.	 (Note that EV is designed to allow the	child to
       handle events that the parent created watchers for.  You	can do that
       just fine.  It's	if you want a fresh event loop with no existing
       watchers	that doesn't work well yet.)

AUTHOR
       Jonathan	Rockway	<jrockway@cpan.org>

COPYRIGHT AND LICENSE
       This software is	copyright (c) 2011 by Jonathan Rockway.

       This is free software; you can redistribute it and/or modify it under
       the same	terms as the Perl 5 programming	language system	itself.

perl v5.32.0			  2011-02-25	       AnyEvent::Subprocess(3)

NAME | VERSION | SYNOPSIS | DESCRIPTION | OVERVIEW | BUGS | AUTHOR | COPYRIGHT AND LICENSE

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

home | help