my $ch = Proc::Background->new(@command); if (defined $ch->pid()) { my $pid = fork(); if (not defined $pid) { die "Cannot fork: $!"; } elsif ($pid == 0) { # child process my $exitcode = $ch->wait() << 8; if ($exitcode == 0) { # call URL } } else { # parent process #waitpid($kidpid, 0); <- do not wait for child exit 0; } } else { # failed to execute exit 127; } #### $ perl /tmp/scratch.pl true [child] Executing true [child] Exiting with exit code 0. [parent] Command has already terminated. (exit code = 0) [parent] Terminating with exit code 0. $ perl /tmp/scratch.pl false [child] Executing false [child] Exiting with exit code 1. [parent] Command has already terminated. (exit code = 1) [parent] Terminating with exit code 1. $ perl /tmp/scratch.pl sleep 5 [child] Executing sleep 5 [parent] Command is still running. [parent] Terminating with exit code 0. [child] Exiting with exit code 0. $ perl /tmp/scratch.pl "sleep 5 ; false" [child] Executing sleep 5 ; false [parent] Command is still running. [parent] Terminating with exit code 0. [child] Exiting with exit code 1. #### #!/usr/bin/env perl use strict; use warnings; use 5.010_001; # essential libraries use English qw( -no_match_vars ); use POSIX qw(:sys_wait_h); my @cmd = @ARGV; my $cmd_str = join ' ', @cmd; my $pid = fork(); if (not defined $pid) { # fork failed die "Cannot fork: $ERRNO\n"; } elsif ($pid == 0) { # child process say("Executing $cmd_str"); my $retval = system(@cmd); my $exitcode = parse_retval($retval); # TODO add URL callback say("[child] Exiting with exit code $exitcode."); exit $exitcode; } else { # parent process # wait a bit to give child process a chance to die prematurely sleep 1; my $cstatus = waitpid($pid, WNOHANG); my $exitcode; if ($cstatus == 0) { $exitcode = 0; say("[parent] Child is still running."); } else { $exitcode = parse_retval(${^CHILD_ERROR_NATIVE}); } say("[parent] Exiting with exit code $exitcode."); exit $exitcode; } sub parse_retval { my $retval = shift; my $signal = $retval & 127; my $have_coredump = $retval & 128; my $exitcode; if ($retval == -1) { # program failed to execute $exitcode = 127; } elsif ($signal) { my $message = "W: Process died with signal $signal!"; if ($have_coredump) { $message .= ' (coredump available)'; } warn($message ."\n"); $exitcode = 255; } else { $exitcode = $retval >> 8; } return $exitcode; } #### #!/usr/bin/env perl use strict; use warnings; use 5.010_001; # essential libraries use English qw( -no_match_vars ); use POSIX qw(:sys_wait_h); use Proc::Simple; my @cmd = @ARGV; my $url; # unused - function not implemented my $child = Proc::Simple->new(); $child->start(\&child, \@cmd, $url); # wait a bit to give child process a chance to die prematurely sleep 1; my $exitcode; if ($child->poll() == 1) { $exitcode = 0; say("[parent] Command is still running."); } else { $exitcode = parse_retval( $child->exit_status() ); say("[parent] Command has already terminated. (exit code = $exitcode)"); } say("[parent] Terminating with exit code $exitcode."); exit $exitcode; sub parse_retval { my $retval = shift; my $signal = $retval & 127; my $have_coredump = $retval & 128; my $exitcode; if ($retval == -1) { # program failed to execute $exitcode = 127; } elsif ($signal) { my $message = "W: Process died with signal $signal!"; if ($have_coredump) { $message .= ' (coredump available)'; } warn($message ."\n"); $exitcode = 255; } else { $exitcode = $retval >> 8; } return $exitcode; } sub child { my @cmd = @{ +shift }; my $url = shift; my $cmd_str = join ' ', @cmd; say("[child] Executing $cmd_str"); my $retval = system(@cmd); my $exitcode = parse_retval($retval); # TODO add URL callback say("[child] Exiting with exit code $exitcode."); exit $exitcode; }