Updated IPC::Cmd to cpan release 0.52
Chris Williams [Fri, 13 Nov 2009 16:19:53 +0000 (16:19 +0000)]
  Changes for 0.52    Fri Nov 13 16:15:11 GMT 2009
  =================================================
  * Added documentation for run_forked()

Porting/Maintainers.pl
cpan/IPC-Cmd/lib/IPC/Cmd.pm

index 021eab4..827b895 100755 (executable)
@@ -812,7 +812,7 @@ use File::Glob qw(:case);
     'IPC::Cmd' =>
        {
        'MAINTAINER'    => 'kane',
-       'DISTRIBUTION'  => 'BINGOS/IPC-Cmd-0.51_01.tar.gz',
+       'DISTRIBUTION'  => 'BINGOS/IPC-Cmd-0.52.tar.gz',
        'FILES'         => q[cpan/IPC-Cmd],
        'CPAN'          => 1,
        'UPSTREAM'      => 'cpan',
index 1a5d020..b9a2326 100644 (file)
@@ -16,7 +16,7 @@ BEGIN {
                         $USE_IPC_RUN $USE_IPC_OPEN3 $CAN_USE_RUN_FORKED $WARN
                     ];
 
-    $VERSION        = '0.51_01';
+    $VERSION        = '0.52';
     $VERBOSE        = 0;
     $DEBUG          = 0;
     $WARN           = 1;
@@ -508,7 +508,91 @@ sub open3_run {
   }
 }
 
-=head2 $ok | ($ok, $err, $full_buf, $stdout_buff, $stderr_buff) = run_forked( command => COMMAND, [verbose => BOOL, buffer => \$SCALAR, timeout => DIGIT] );
+=head2 $hashref = run_forked( command => COMMAND, { child_stdin => SCALAR, timeout => DIGIT, stdout_handler => CODEREF, stderr_handler => CODEREF} );
+
+C<run_forked> is used to execute some program,
+optionally feed it with some input, get its return code
+and output (both stdout and stderr into seperate buffers).
+In addition it allows to terminate the program
+which take too long to finish.
+
+The important and distinguishing feature of run_forked
+is execution timeout which at first seems to be
+quite a simple task but if you think
+that the program which you're spawning
+might spawn some children itself (which
+in their turn could do the same and so on)
+it turns out to be not a simple issue.
+
+C<run_forked> is designed to survive and
+successfully terminate almost any long running task,
+even a fork bomb in case your system has the resources
+to survive during given timeout.
+
+This is achieved by creating separate watchdog process
+which spawns the specified program in a separate
+process session and supervises it: optionally
+feeds it with input, stores its exit code,
+stdout and stderr, terminates it in case
+it runs longer than specified.
+
+Invocation requires the command to be executed and optionally a hashref of options:
+
+=over
+
+=item C<timeout>
+
+Specify in seconds how long the command may run for before it is killed with with SIG_KILL (9) 
+which effectively terminates it and all of its children (direct or indirect).
+
+=item C<child_stdin>
+
+Specify some text that will be passed into C<STDIN> of the executed program.
+
+=item C<stdout_handler>
+
+You may provide a coderef of a subroutine that will be called a portion of data is received on 
+stdout from the executing program.
+
+=item C<stderr_handler>
+
+You may provide a coderef of a subroutine that will be called a portion of data is received on 
+stderr from the executing program.
+
+=back
+
+C<run_forked> will return a HASHREF with the following keys:
+
+=over
+
+=item C<exit_code>
+
+The exit code of the executed program.
+
+=item C<timeout>
+
+The number of seconds the program ran for before being terminated, or 0 if no timeout occurred.
+
+=item C<stdout>
+
+Holds the standard output of the executed command
+(or empty string if there were no stdout output; it's always defined!)
+
+=item C<stderr>
+
+Holds the standard error of the executed command
+(or empty string if there were no stderr output; it's always defined!)
+
+=item C<merged>
+
+Holds the standard output and error of the executed command merged into one stream
+(or empty string if there were no output at all; it's always defined!)
+
+=item C<err_msg>
+
+Holds some explanation in the case of an error.
+
+=back
 
 =cut
 
@@ -591,8 +675,9 @@ sub run_forked {
   #    print "child $pid started\n";
 
       my $child_finished = 0;
-      my $child_stdout = "";
-      my $child_stderr = "";
+      my $child_stdout = '';
+      my $child_stderr = '';
+      my $child_merged = '';
       my $child_exit_code = 0;
 
       my $got_sig_child = 0;
@@ -646,6 +731,7 @@ sub run_forked {
 
         while (my $l = <$child_stdout_socket>) {
           $child_stdout .= $l;
+          $child_merged .= $l;
 
           if ($opts->{'stdout_handler'} && ref($opts->{'stdout_handler'}) eq 'CODE') {
             $opts->{'stdout_handler'}->($l);
@@ -653,6 +739,7 @@ sub run_forked {
         }
         while (my $l = <$child_stderr_socket>) {
           $child_stderr .= $l;
+          $child_merged .= $l;
 
           if ($opts->{'stderr_handler'} && ref($opts->{'stderr_handler'}) eq 'CODE') {
             $opts->{'stderr_handler'}->($l);
@@ -687,11 +774,12 @@ sub run_forked {
       my $o = {
         'stdout' => $child_stdout,
         'stderr' => $child_stderr,
+        'merged' => $child_merged,
         'timeout' => $child_timedout ? $opts->{'timeout'} : 0,
         'exit_code' => $child_exit_code,
         };
 
-      my $err_msg = "";
+      my $err_msg = '';
       if ($o->{'exit_code'}) {
         $err_msg .= "exited with code [$o->{'exit_code'}]\n";
       }
@@ -1541,6 +1629,8 @@ C<IPC::Run>, C<IPC::Open3>
 Thanks to James Mastros and Martijn van der Streek for their
 help in getting IPC::Open3 to behave nicely.
 
+Thanks to Petya Kohts for the C<run_forked> code.
+
 =head1 BUG REPORTS
 
 Please report bugs or other issues to E<lt>bug-ipc-cmd@rt.cpan.orgE<gt>.