=head1 NAME

Apache::SubProcess -- Executing SubProcesses under mod_perl





=head1 Synopsis

  use Apache::SubProcess ();
  
  use Config;
  use constant PERLIO_IS_ENABLED => $Config{useperlio};
  
  # pass @ARGV / read from the process
  $command = "/tmp/argv.pl";
  @argv = qw(foo bar);
  $out_fh = $r->spawn_proc_prog($command, \@argv);
  $output = read_data($out_fh);
  
  # pass environment / read from the process
  $command = "/tmp/env.pl";
  $r->subprocess_env->set(foo => "bar");
  $out_fh = $r->spawn_proc_prog($command);
  $output = read_data($out_fh);
  
  # write to/read from the process
  $command = "/tmp/in_out_err.pl";
  ($in_fh, $out_fh, $err_fh) = $r->spawn_proc_prog($command);
  print $in_fh "hello\n";
  $output = read_data($out_fh);
  $error  = read_data($err_fh);
  
  # helper function to work w/ and w/o perlio-enabled Perl
  sub read_data {
      my($fh) = @_;
      my $data;
      if (PERLIO_IS_ENABLED || IO::Select->new($fh)->can_read(10)) {
          $data = <$fh>;
      }
      return defined $data ? $data : '';
  }




=head1 Description

C<Apache::SubProcess> provides the Perl API for running and
communicating with processes spawned from mod_perl handlers.

At the moment it's possible to spawn only external program in a new
process. It's possible to provide other interfaces, e.g. executing a
sub-routine reference (via C<B::Deparse>) and may be spawn a new
program in a thread (since the APR api includes API for spawning
threads, e.g. that's how it's running mod_cgi on win32).


=head1 API


=head2 C<spawn_proc_prog>

Spawn a sub-process and return STD communication pipes:

  $out_fh                    = $r->spawn_proc_prog($command);
  $out_fh                    = $r->spawn_proc_prog($command, \@argv);
  ($in_fh, $out_fh, $err_fh) = $r->spawn_proc_prog($command);
  ($in_fh, $out_fh, $err_fh) = $r->spawn_proc_prog($command, \@argv);

=over 4

=item obj: C<$r>
( C<L<Apache::RequestRec object|docs::2.0::api::Apache::RequestRec>> )

=item arg1: C<$command> ( string )

The command to be C<$exec()>'ed.

=item opt arg2: C<\@argv> ( ARRAY ref )

A reference to an array of arguments to be passed to the process as
the process' C<ARGV>.

=item ret: ...

In SCALAR context returns the output filehandle of the spawned
process.

In LIST context returns the input, outpur and error filehandles of the
spawned process.

=item since: 1.99_15

=back

It's possible to pass environment variables as well, by calling:

  $r->subprocess_env->set($key => $value);

before spawning the subprocess.

There is an issue with reading from the read filehandle (C<$in_fh>)):

A pipe filehandle returned under perlio-disabled Perl needs to call
select() if the other end is not fast enough to send the data, since
the read is non-blocking.

A pipe filehandle returned under perlio-enabled Perl on the other hand
does the select() internally, because it's really a filehandle opened
via C<:APR> layer, which internally uses APR to communicate with the
pipe. The way APR is implemented Perl's select() cannot be used with
it (mainly because select() wants fileno() and APR is a crossplatform
implementation which hides the internal datastructure).

Therefore to write a portable code, you want to use select for
perlio-disabled Perl and do nothing for perlio-enabled Perl, hence you
can use something similar to the C<read_data()> wrapper shown in the
L<Synopsis|/Synopsis> section.

Several examples appear in the L<Synopsis|/Synopsis> section.



=head1 See Also

L<mod_perl 2.0 documentation|docs::2.0::index>.




=head1 Copyright

mod_perl 2.0 and its core modules are copyrighted under
The Apache Software License, Version 2.0.




=head1 Authors

L<The mod_perl development team and numerous
contributors|about::contributors::people>.

=cut
