How to kill all child processes except itself?

Z

zeal

I have a perl script, part of it as below:
-------------------------------------------
$rc = eval{
my ($rc);
local $SIG{ALRM} = sub { die "Timeout" };
alarm $timeout;
$rc = 0xffff & system $cmd;
alarm 0;
return $rc;
};
if ( $@ && $@ =~ /Timeout/ ) {
local $SIG{INT} = 'IGNORE';
kill INT => -$$;
$rc = 0x9999;
}
--------------------------------------------

What I want to do is that kill all child processes after the timeout
but keep the script itself alive. Actually I need to kill all processes
(the whole process group) invoked from the system() call. The reason I
need to use system is, I need to analysis the return value "$rc".
In most cases, the system() can finish before the timeout, however, in
some cases, it will time out, then I want to kill all the processes
after the timeout.

The way I used to do the kill is
-----------------------------
local $SIG{INT} = 'IGNORE';
kill INT => -$$;
-----------------------------
I got this from somewhere, it's said that when a SIG sent to a negative
pid, it will be sent to the whole process group. Since I "INGORE"
myself, then this shouls satisfy my requirement.

I run this script in LINUX system.
Most of the case, it works fine. However, sometimes, I found that when
the script is finished, some child processes are still running, which
means that they were not killed.

And use "pstree -p", I found that those alive child processes's parent
PID is changed, not the pid of the perl script process.

My question is how can I completely kill all the child processess?

BTW: the "$cmd" is used to call "make -f somemakefile", several
generation of child processes may invoked during the system().

One example,
when I run my script.

31166 2416 0 04:01 pts/0 00:00:00 /usr/bin/perl -w ./regtests.pl


After it's done, some timeout processes are already killed, but two of
them are still alive

pstree -p
+-sh(31844)---make(31845)---sim(31851)
+-sh(31856)---make(31857)---sim(31863)

The parent id is already changed ...

On one of my debian platform (kernel 2.6), this always happens, most of
child processes are alive. On other linux platform (including debian
(kernel 2.4), redhat, gentoo), only some of them can not be killed.
Any solutions???

Thanks very much!
 
B

Brian McCauley

zeal wrote:

What I want to do is that kill all child processes after the timeout
but keep the script itself alive. Actually I need to kill all processes
(the whole process group) invoked from the system() call. The reason I
need to use system is, I need to analysis the return value "$rc".
In most cases, the system() can finish before the timeout, however, in
some cases, it will time out, then I want to kill all the processes
after the timeout.

The way I used to do the kill is
-----------------------------
local $SIG{INT} = 'IGNORE';
kill INT => -$$;
-----------------------------
I got this from somewhere, it's said that when a SIG sent to a negative
pid, it will be sent to the whole process group. Since I "INGORE"
myself, then this shouls satisfy my requirement.

I run this script in LINUX system.
Most of the case, it works fine. However, sometimes, I found that when
the script is finished, some child processes are still running, which
means that they were not killed.

And use "pstree -p", I found that those alive child processes's parent
PID is changed, not the pid of the perl script process.

Is it 1 ? When a process dies it's children are adopted by process 1.

Note that a process group is not the same thing as all the decentants of
a process, it is all the processes with the same process group id. When
a process forks its new child will inherit the parent's PGID. But any
process can at any time decide to break away form its parent's process
group and start its own (with a PGID equal to its PID).

I suggest you look at the PGID of the children that won't die to see if
they have broken away from the group.

A neat trick that may help in this cases is to create the tree of
subrocesses with STDERR/STDOUT redirected to a pipe or pipes then they
all get killed with a SIGPIPE simply by closing these pipes. This of
course only works if they don't redirect STDERR and STDOUT.

This is all more to do with Unix/Linux than it is to do with Perl.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top