Killing all child processes?

Kevin kfrederick at bigfoot.com
Tue Apr 23 22:23:36 EDT 2002


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."



More information about the Python-list mailing list