I have some Perl code that generates a number of child processes. The basic code is as follows:
my $forked = 0;
my $err = 0;
my $Processes_To_Use_After_Calc=10;
print "Parent ($$) has started\n";
for my $ispawn (1 .. $Processes_To_Use_After_Calc){
my $child_pid = fork();
die "Cannot fork: $!" if !defined $child_pid; # system overload
if(defined $child_pid && $child_pid > 0) {
## Parent
$forked++;
} elsif(defined $child_pid){
#
# Here some calculations are performed
#
print "Child $$ has finished (number $ispawn) \n";
}
}
for(1..$forked) {
my $child_pid = wait();
}
All fairly standard stuff. Now, I would like to know if any of the child processes crash (failed to terminate correctly). Clearly if the last statement of each child process is not printed I could assume there was a problem. However I would like another method that would exit the parent program completely and close all child processes that were still open if one of the child processes crashes. Is this possible?
wait
sets $?
Behaves like
wait(2)
on your system: it waits for a child process to terminate and returns the pid of the deceased process, or-1
if there are no child processes. The status is returned in$?
and ${^CHILD_ERROR_NATIVE}
.
So,
my $child_pid = wait();
if ( $? == -1 ) { die "wait failed: $!\n"; }
elsif ( $? & 0x7F ) { warn "Child $child_pid killed by signal ".( $? & 0x7F )."\n"); }
elsif ( $? >> 8 ) { warn "Child $child_pid exited with error ".( $? >> 8 )."\n"); }
else { print "Child $child_pid exited successfully\n"; }
If the program truly crashed, you'd get Child killed by signal 11
, which is SIGSEGV
.
If it threw an uncaught exception, you'd likely get Child exited with error XXX
. The exact value will vary by program and could be meaningless. By default, Perl uses $! || ($? >> 8) || 255
for exit value on an uncaught exception.