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

Reply via email to