clintonm9 has asked for the wisdom of the Perl Monks concerning the following question:

I need to split up stdout and stderr from a shell process i am executing in perl. I went down the path of using CaptureOutput perl module to accomplish my objective. I am now having problems with the Success flag if I am in a child process with $SIG{CHLD} = 'IGNORE'; set. Please see my sample below and let me know if there is anything that I could do to make this process return success like it should. If not is there another way to handle getting stdout and stderr into different scalars that would be 100% reliable?
#!/usr/bin/perl use Data::Dumper; use IO::CaptureOutput qw/capture_exec/; # The first test shows the Success = 1 &runCommand(); # Now the same thing in a child process shows Success = 1 unless ( $pid = fork ) { &runCommand(); exit; } # Now child process with IGNORE set, shows Success = 0 $SIG{CHLD} = 'IGNORE'; unless ( $pid = fork ) { &runCommand(); exit; } sub runCommand { ($stdout, $stderr, $success, $exit_code) = capture_exec('perl', '- +e', 'print "Test"'); print "stdout: $stdout\n"; print "stderr: $stderr\n"; print "Success: $success\n"; print "exit code: $exit_code\n"; }
Thanks
  • Comment on Using IO::CaptureOutput in a child process to caputre STDOUT and STDERR
  • Download Code

Replies are listed 'Best First'.
Re: Using IO::CaptureOutput in a child process to caputre STDOUT and STDERR
by Khen1950fx (Canon) on Apr 10, 2011 at 08:57 UTC
    I think that you were missing a few things, primarily a reaper subroutine---without that, it'll always return -1. Here's how I would do it:
    !/usr/bin/perl use strict; use warnings; use IO::CaptureOutput qw(capture capture_exec); use Proc::Killall; use POSIX qw(:signal_h :errno_h :sys_wait_h); &runCommand(); my $pid; unless ( $pid = fork ) { &runCommand(); exit; } $SIG{'CHLD'} = \&Reaper; unless ( $pid = fork ) { &runCommand(); exit; } sub runCommand { my ($stdout, $stderr, $success, $exit_code) = capture_exec('perl', '-e', 'print "Test"'); print "stdout: $stdout\n"; print "stderr: $stderr\n"; print "Success: $success\n"; print "exit code: $exit_code\n"; } sub Reaper { my $pid; waitpid(-1, &WNOHANG); } killall('HUP', -$$);
    Update: added a kill.
      small comment: there is no "&" in front of WNOHANG.
      sub reaper { my $kid; while ( ( $kid = waitpid(-1, WNOHANG) >0 ) ){}; }
        small comment: there is no "&" in front of WNOHANG.

        Because you removed it! :)

        $ perl -Mstrict -Mwarnings -e " print WNOHANG " Name "main::WNOHANG" used only once: possible typo at -e line 1. print() on unopened filehandle WNOHANG at -e line 1.