Killing all child processes?
Noah
noah at noah.org
Wed Apr 24 03:59:58 EDT 2002
You want to kill the process group.
Practically the only change you need to make is to
call os.kill with the negative of the child pid.
So in the line that reads:
os.kill(child_pid, 9)
You need to change it to read:
os.kill(-child_pid, 9)
That kills the given pid and every process that has a
process group id with the same number as the child_pid.
You ensured that all the children had the same group as
the first child (session leader) when you wrote this line:
os.setpgid(0, 0)
But note that Python has a special call just for that:
os.setpgrp() # Sets process session leader.
FYI, execlp() takes two arguments because the
first one is the path to the command to exec and the second
one is supposed to become the argv[0] of the command.
But it doesn't seem to do that. I'm not sure why.
Yours,
Noah
-----Original Message-----
From: python-list-admin at python.org
[mailto:python-list-admin at python.org]On Behalf Of Kevin
Sent: Tuesday, April 23, 2002 7:24 PM
To: python-list at python.org
Subject: Killing all child processes?
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