简体   繁体   English

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

[英]Python SIGTERM handler is not activated in subprocess

I want to gracefully release some expensive system resource in my code with event handler. 我想使用事件处理程序在代码中优雅地释放一些昂贵的系统资源。 The problem is that the event handler is registered in a forked sub-process (yes, I have to put the event handler there in sub-process, since the resource is allocated after fork) and I want the sub-processes terminate when parent process dies. 问题是事件处理程序在派生的子流程中注册(是的,我必须将事件处理程序放在子流程中,因为资源是在fork之后分配的),并且我希望子流程在父流程时终止死亡。 However, the code does not work as my expectation. 但是,该代码不符合我的期望。

Here is a runnable example: 这是一个可运行的示例:

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

The code does the following: 该代码执行以下操作:

  1. instruct OS to turn parent die signal to a SIGTERM; 指示OS将父级死亡信号转给SIGTERM;
  2. fork a sub-process; 派生一个子流程;
  3. if child process, register signal handler and wait for parent's termination. 如果是子进程,则注册信号处理程序并等待父进程终止。

On my platform, the output is 在我的平台上,输出为

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

It seems the handler is not activated. 看来处理程序未激活。

Anything wrong with my code or understanding? 我的代码或理解有什么问题吗?

Configuration on my box is 我的盒子上的配置是

2.6.18-238.el5 x86_64 Python 2.6 2.6.18-238.el5 x86_64 Python 2.6

Any hints will be highly appreciate, thank you! 任何提示将不胜感激,谢谢!

from prctl 来自prctl

PR_SET_PDEATHSIG (since Linux 2.1.57) Set the parent process death signal of the calling process to arg2 (either a signal value in the range 1..maxsig, or 0 to clear). PR_SET_PDEATHSIG(从Linux 2.1.57开始)将调用进程的父进程死亡信号设置为arg2(信号值在1..maxsig范围内,或在0范围内以清除)。 This is the signal that the calling process will get when its parent dies. 这是调用进程在其父进程死亡时将得到的信号。 This value is cleared for the child of a fork (2) and (since Linux 2.4.36 / 2.6.23) when executing a set-user-ID or set-group-ID binary. 执行set-user-ID或set-group-ID二进制文件时,将为fork (2)和(自Linux 2.4.36 / 2.6.23起) 的子代清除此值

so you essentially ensure that your parent dies with it's parent, but say nothing about your child process. 因此,您基本上可以确保父母与父母父母去世,但对您的子进程一无所知。

if you add: 如果添加:

dieWithParent()

after you fork then it behaves correctly 您分叉后,它的行为正确

If this is an attempt to write a daemon you should look up double forking. 如果尝试编写守护程序,则应查找双叉。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM