I have a series of test scripts that launches server subprocesses of
different kinds - httpd, HTTP::Server::Simple, etc. A test script
might launch multiple instances of each type of server. I'd like to
behave well and kill all these children before the test exits. But
it's a pain to keep track of all the child pids, especially when the
code that creates the subprocess is many levels down from the test
script itself.
Is there any way to automatically kill all the child processes created
by a script (and their descendents)? For example, can I catch each
subprocess creation somehow and record the pid in a global array?
At first I tried using Proc::ProcessTable to find all the processes
where ppid = $$:
sub kill_my_children {
my $self = shift;
my $t = new Proc::ProcessTable;
my $get_child_pids = sub {
map { $_->pid } grep { $_->ppid == $$ } @{ $t->table };
};
my $send_signal = sub {
my ( $signal, $pids ) = @_;
explain( "sending signal $signal to " . join( ", ", @
$pids ) . "\n" );
kill $signal, @$pids;
};
if ( my @child_pids = $get_child_pids->() ) {
$send_signal->( 15, \...@child_pids );
for ( my $i = 0 ; $i < 3 && $get_child_pids->() ; $i++ ) {
sleep(1);
}
if ( @child_pids = $get_child_pids->() ) {
$send_signal->( 9, \...@child_pids );
}
}
}
But that doesn't work, because some servers, like httpd, launch in
such a way that the parent httpd process ends up with ppid = 1.
Thanks
Jon