Ensuring child processes die on exit with PrCtl
25 November 2012One issue you encounter when writing software which starts child processes is making sure the children terminate when the parent does. If the child processes are well behaved, or if the parent always exits cleanly under controlled conditions, this might not be much of an issue. But if you find youself stuck working with other, badly behaved software (looking at you PhantomJS) there is a simple solution in the form of Linux’s prctl module.
This module allows a process to specify a signal it should be sent when its
parent dies, which you should do after forking the child process but
before exec’ing the external code. Python’s subprocess
module provides a hook for exactly
this purpose (the preexec_fn
argument to Popen
). And, while the stdlib doesn’t
provide a native interface to prctl
, ctypes comes to the resuce.
Putting it all together, the following snippet of code does the business:
import signal
from ctypes import cdll
# Constant taken from http://linux.die.net/include/linux/prctl.h
PR_SET_PDEATHSIG = 1
class PrCtlError(Exception):
pass
def on_parent_exit(signame):
"""
Return a function to be run in a child process which will trigger
SIGNAME to be sent when the parent process dies
"""
signum = getattr(signal, signame)
def set_parent_exit_signal():
# http://linux.die.net/man/2/prctl
result = cdll['libc.so.6'].prctl(PR_SET_PDEATHSIG, signum)
if result != 0:
raise PrCtlError('prctl failed with error code %s' % result)
return set_parent_exit_signal
Usage is simple:
subprocess.Popen(['some-executable'], preexec_fn=on_parent_exit('SIGTERM'))
Canonical version is available as a Gist.
comments powered by Disqus