use POSIX qw(:sys_wait_h); use IO::Handle; my %scythe; # a scythe for the REAPER (see FAQ); $SIG{CHLD} = \&REAPER; # set handling of zombie child processes. STDOUT->autoflush; # make sure output is flushed before forking # setup an interupt handler # kills every pid used as a key in %scythe #################### $SIG{INT} = sub { print "\nCleaning: "; print join(", ", keys(%scythe)); print "\n"; kill('INT', keys %scythe); print "done with: "; print join(", ", keys(%scythe)); die "\n"; }; #### MAIN #### #### END MAIN, begin defs #### sub phork { # we will call fork and return a pid. The child will exec with all args # and suppress the child's output; my $pid; if ($pid = fork) { # fork the process; #parent return $pid; }else { #child die "CANNOT FORK!!\n" unless defined $pid; close(STDOUT); # suppressing output close(STDERR); # suppressing output {exec(@_);}; # calls exec with current @_ exit(1); # exec may maybe fail... maybe. } } sub baitKiller { # This functions is a dummy to be used to be added to %scythe for a $pid # This way when the interupt is called, the process with the $pid will # be cleaned up (killed) so it doesn't keep running after its parent's # death. If you'd rather it did, just don't assign anything in %scythe # for the key of it's $pid. return "Come get some!"; } sub REAPER { # we reap child processes, and post process it. # note: this sub relies on a global %scythe # sort of... if a $scythe{$pid} is defined, it will assume that its a # reference to a function that takes $pid and $exit_value as args # and presumably does something useful with that. Then it deletes the # $scythe{$pid} hash entry. is it not nifty? # local vars my $pid; my $exit_value; $pid = waitpid(-1, &WNOHANG); if($pid == -1) { # no child waiting } elsif (WIFEXITED($?)) { # the process exited, get exit value. my $slot; my $state; $exit_value = $? >> 8; if (exists($scythe{$pid})) { $scythe{$pid}->( $pid, $exit_value ); delete($scythe{$pid}); } else { # we're reaping something we didn't sow or didn't care about; return; } } else { # false alarm on $pid } $SIG{CHLD} = \&REAPER; #reset signal handling. } #end sub REAPER