子进程中未激活Python SIGTERM处理程序

时间:2014-06-20 09:44:15

标签: python linux libc

我希望使用事件处理程序在我的代码中优雅地释放一些昂贵的系统资源。 问题是事件处理程序是在forked子进程中注册的(是的,我必须将事件处理程序放在子进程中,因为资源是在fork之后分配的)我希望子进程在父进程时终止死亡。 但是,代码不能满足我的期望。

这是一个可运行的例子:

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

代码执行以下操作:

  1. 指示操作系统将父模信号转换为SIGTERM;
  2. fork一个子流程;
  3. 如果子进程,注册信号处理程序并等待父进程终止。
  4. 在我的平台上,输出是

    $ python main.py
    In foo.
    Subprocess spawned.
    dying...
    

    似乎处理程序未激活。

    我的代码或理解有什么问题吗?

    我的盒子上的配置是

      

    2.6.18-238.el5 x86_64   Python 2.6

    任何提示都将非常感谢,谢谢!

2 个答案:

答案 0 :(得分:2)

来自prctl

  

PR_SET_PDEATHSIG(自Linux 2.1.57起)设置父进程死亡   调用进程到arg2的信号(信号中的信号值)   范围1..maxsig,或0表示清除)。这是呼叫的信号   当父母去世时,过程就会得到。 清除此值   执行a时,fork的子项(2)和(自Linux 2.4.36 / 2.6.23起)   set-user-ID或set-group-ID binary。

因此,您基本上确保您的父母与其父母一起死亡,但对您的子女流程一无所知。

如果你添加:

dieWithParent()
你分叉后

它的行为正确

答案 1 :(得分:-1)

如果这是尝试编写守护进程,则应该查找双重分支。

例如:http://code.activestate.com/recipes/66012-fork-a-daemon-process-on-unix/