Python中的SIGTERM处理程序在子进程中未激活
我想在我的代码中优雅地释放一些昂贵的系统资源,使用事件处理器来实现。问题是,这个事件处理器是在一个分叉的子进程中注册的(是的,我必须把事件处理器放在子进程里,因为资源是在分叉后分配的),我希望当父进程结束时,子进程也能终止。但是,代码的表现并没有如我所预期的那样。
这里有一个可以运行的示例:
import time
import os
import signal
PRCTL=None
# get prctl from libc
def getPRCTL():
global PRCTL
if PRCTL is None:
import ctypes
PRCTL = ctypes.CDLL("libc.so.6")["prctl"]
return PRCTL
def dieWithParent():
prctl = getPRCTL()
prctl(1, signal.SIGTERM) # 1 = PR_SET_PDEATHSIG
def foo():
print "In foo."
def handler(signo, frame):
print "Handler is activated."
signal.signal(signal.SIGTERM, handler)
time.sleep(10) # in case sub-process terminates first.
if __name__ == '__main__':
dieWithParent()
pid = os.fork()
if 0 == pid:
foo()
else:
print "Subprocess spawned."
print "dying..."
这段代码做了以下几件事:
- 指示操作系统将父进程的死亡信号转为SIGTERM信号;
- 创建一个子进程;
- 如果是子进程,就注册信号处理器并等待父进程的结束。
在我的平台上,输出结果是
$ python main.py
In foo.
Subprocess spawned.
dying...
看起来处理器并没有被激活。
我的代码或理解上有什么问题吗?
我这边的配置是
2.6.18-238.el5 x86_64 Python 2.6
任何提示都非常感谢,谢谢!
2 个回答
-1
如果你是在尝试写一个守护进程(daemon),那么你应该了解一下双重分叉(double forking)。
比如说,你可以参考这个链接: http://code.activestate.com/recipes/66012-fork-a-daemon-process-on-unix/
2
来自 prctl
PR_SET_PDEATHSIG(自 Linux 2.1.57 起)是用来设置调用进程的父进程死亡信号的。这个信号可以是一个在 1 到 maxsig 范围内的信号值,或者是 0(表示不设置)。当调用进程的父进程死掉时,它会收到这个信号。这个值在调用 fork(创建子进程)时会被清除(2),并且(自 Linux 2.4.36 / 2.6.23 起)在执行设置用户 ID 或组 ID 的程序时也会被清除。
所以,简单来说,你确保你的父进程会在它的父进程死掉时也死掉,但这对你的子进程没有影响。
如果你添加:
dieWithParent()
在你创建子进程之后,这样做就能正常工作了。