[Ilugc] Killing an enitre process tree

  • From: girishvenkatachalam@xxxxxxxxx (Girish Venkatachalam)
  • Date: Sun Oct 29 22:44:32 2006

On Sun, Oct 29, 2006 at 07:44:55PM +0530, Chandrashekar Babu wrote:

Hi,  

 The situation is so. Py_Prog1 --> Shell --> Prog2. Now I want to kill
 both Shell and Prog2. How do I do that?

You can try using killpg() system call or trying the kill() system call with 
the negated PID. 

Yet, there is no reliable/straight-forward mechanism on UNIX/Linux to
kill an entire process-tree. It is very likely that one of the child process
deep down the process hierarchy could detach from the current
 process-group/session by performing a setsid() system call and you 
will have no direct control over it.

Iterating/Recursing down the process tree (which is complicated) 
determining the process-id relating to their parent's process-id/hierarchy 
and killing one by one could be the only way out.

Good luck :-)

I *think* this should give you what you want. As already told this is not 
bullet proof or reliable but then I want you to be guinea pig for my program. 
:-)

regards,
Girish

#!/usr/bin/env perl

# This kills the child processes of a process tree

use strict;

my (@f,$ln,$mypid,$parentprocess) = ();
my @subprocesses = ();
my $capture_begin = 0;


sub kill_children() {
        for (@_) {

                while( /\((.*?)\)/g ) {
                        if($1 eq $mypid) {
                                next;
                        }
                        printf "Killing PID %d\n",$1;
                        `kill $1`;      
                }

        }
}

$parentprocess = shift;
if ( $parentprocess eq "") {
        print "Please specify name of parent process\n";
        exit 128;
}
# Most important line :-)

@f = `pstree -Apl | tr -s ' '`;

for $ln  ( @f ) {
        if( $ln =~ /^ \|-/) {
                last if ($capture_begin == 1);
                if($ln =~ /^ \|-$parentprocess\((.*?)\)/) {
                        $capture_begin = 1;
                        $mypid = $1;
                        push(@subprocesses,"$ln"); 
                }
        }
        else {
                if( $capture_begin == 1) {
                        push(@subprocesses,"$ln"); 
                }
        }
}
&kill_children(@subprocesses);


Other related posts: