Killing all child processes?

Martin Barnard martinb at otenet.gr
Wed Apr 24 03:51:48 EDT 2002


Shouldn't you be looking into each child process having a handler to
pass on any SIG events it receives from STDIN (or parent)?
e.g. for each child process, take a PID and store it.
If parent receives a SIG event, then pass it down to child processes.
Each child process should have the same handler code in also (possibly
with a signal to parent if it quits, so that the list of child processes
is current for each parent).
Sorry if it sounds a little strange, I've just woken up, and am rambling
a little :)

Let's see if I can visualise:

   Parent_1
      |
  ____|____
 |         |
Child1   Child2
  |
Child3
 
Now, if I send a SIGKILL to Parent_1, it will pass on <SIGKILL> to
Child1 and Child2. Child1 will pass on <SIGKILL> to Child3 via the same
mechanism.

The only potential problem would be if a child branch died before hand,
and the PID was taken by another process that Parent_1 could kill (same
user).

Hope this helps, if not, just ignore my waffling.

Martin.

On Wed, 2002-04-24 at 05:23, Kevin wrote:
> Hi all,
> 
> I can't seem to get my python program to kill all the child prcoesses
> that it may fork. Is this possible?
> 
> I've researched usenet+the web and read subproc.py from
> ftp.python.org, but still no go.
> 
> My latest attempt was a python script that forks itself, uses setpgid,
> then the child does an execl(). The execl'd program creates some
> children. Meanwhile, the parent decides time is up on the child and
> tries to kill everything, but  my os.kill(pid,9) only succeeds in
> killing the child aka the execvp'd process.
> 
> There's another bug that I haven't yet addressed about the parent
> waiting around when the child doesn't write to either of the pipes.
> But that'd not my focus now, so don't worry about that; I just want
> all the children to die.
> 
> My full code it at the bottom. Hints, anyone? This is on Linux and
> FreeBSD.
> 
> Thanks,
> Kevin
> 
> ---Full code follows---
> ---- pcontrol.py below
> #!/usr/bin/python
> #
> # pcontrol.py
> #
> 
> import os
> import sys
> import signal
> 
> _alarm = "request timed out"
> 
> time = 5
> 
> cmd="sh1.sh"
> 
> ###########################################################
> 
> def alarm_handler(a , b):
>     global _alarm
>     signal.alarm(0)
>     raise _alarm
> 
> ###########################################################
> 
> # Okay, let's do this the hard way: create two unnamed
> # pipes for stdout/err. Then, fork this process, and the
> # child becomes the new command and shoves their output
> # onto the pipes, while the parent waits for the child to die.
> 
> # Create two named pipes
> child_out_r, child_out_w = os.pipe()
> child_err_r, child_err_w = os.pipe()
> 
> # Let's fork a child that gets replaced with the test process - krf
> child_pid = os.fork()
> 
> if (child_pid != 0):
>     # We're the parent
> 
>     os.close(child_out_w) # the parent won't read the pipes
>     os.close(child_err_w)
> 
>     os.setpgid(child_pid, 0)
> 
>     # Now do the timing...
>     signal.signal(signal.SIGALRM, alarm_handler)
>     signal.alarm(time)
> 
>     try:
>         child_pid, child_status = os.waitpid(child_pid, 0); # wait for
> child
>     except OSError:
>         print("OSError... did the executable time out?")
>         child_status = -1 # this is the same as a timeout for now
>     except _alarm:
>         print("Timed out")
>         # kill it!
>         os.kill(child_pid, 9)
>         child_status = -1 # timeout
> 
>     signal.alarm(0) # clean up alarm
> 
> else:
>     # We're the child
>     os.setpgid(0, 0) # now the child is it's group leader (?)
> 
>     # Redirect error to our pipes
>     os.close(child_out_r) # the child won't read the pipes
>     os.close(child_err_r)
>     os.dup2(child_out_w, sys.stdout.fileno())
>     os.dup2(child_err_w, sys.stderr.fileno())
> 
>     # replace the process
>     os.execl(cmd, cmd) #strange, but execl->execv needs a second
> arg...
>     # the child is no more... (assuming success)
>     
> print "Status = ", child_status
> print "Child stdout [",os.read(child_out_r,999),"]"
> print "Child stderr [",os.read(child_err_r,999),"]"
> 
> 
> ------- sh1.sh below
> #!/bin/sh
> 
> echo "This is processs (1) $$."
> sh2.sh &
> sh3.sh &
> sleep 600
> echo "Process (1) $$ exiting."
> 
> ------- sh2.sh below
> #!/bin/sh
> 
> echo "This is processs (2) $$."
> sleep 600
> echo "Process (2) $$ exiting."
> 
> ------- sh3.sh below
> #!/bin/sh
> 
> echo "This is processs (3) $$."
> sleep 600
> echo "Process (3) $$ exiting."
> -- 
> http://mail.python.org/mailman/listinfo/python-list
> 
-- 
Experience is that marvelous thing that enables you recognize a mistake
when you make it again.
		-- F. P. Jones






More information about the Python-list mailing list