Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/mongodb/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python进程在重新启动后停止响应SIGTERM/SIGINT_Python_Ipc_Freebsd - Fatal编程技术网

Python进程在重新启动后停止响应SIGTERM/SIGINT

Python进程在重新启动后停止响应SIGTERM/SIGINT,python,ipc,freebsd,Python,Ipc,Freebsd,我对一些使用看门狗进程运行的python进程有一个奇怪的问题 看门狗进程是用python编写的,是父进程,它有一个名为start_child(name)的函数,该函数使用subprocess.Popen打开子进程。记录Popen对象,以便看门狗可以使用poll()监视进程,并在需要时最终以terminate()结束进程。 如果子对象意外死亡,看门狗将再次调用start_child(name)并记录新的Popen对象 有7个子进程,它们都是python。如果我手动运行任何子级,我可以使用kill发

我对一些使用看门狗进程运行的python进程有一个奇怪的问题

看门狗进程是用python编写的,是父进程,它有一个名为start_child(name)的函数,该函数使用subprocess.Popen打开子进程。记录Popen对象,以便看门狗可以使用poll()监视进程,并在需要时最终以terminate()结束进程。 如果子对象意外死亡,看门狗将再次调用start_child(name)并记录新的Popen对象

有7个子进程,它们都是python。如果我手动运行任何子级,我可以使用kill发送SIGTERM或SIGINT,并获得我期望的结果(过程结束)

但是,当从看门狗进程运行时,子进程将仅在第一个信号后结束。当看门狗重新启动子进程时,新的子进程不再响应SIGTERM或SIGINT。我不知道是什么原因造成的

watchdog.py

class watchdog:
    # <snip> various init stuff

    def start(self):
        self.running = true

        kids = ['app1', 'app2', 'app3', 'app4', 'app5', 'app6', 'app7']
        self.processes = {}

        for kid in kids:
            self.start_child(kid)

        self.thread = threading.Thread(target=self._monitor)
        self.thread.start()

        while self.running:
            time.sleep(10)

    def start_child(self, name):
        try:
            proc = subprocess.Popen(name)
            self.processes[name] = proc
        except:
            print "oh no"
        else:
            print "started child ok"

    def _monitor(self):
        while self.running:
            time.sleep(1)
            if self.running:
                for kid, proc in self.processes.iteritems():
                    if proc.poll() is not None: # process ended
                        self.start_child(kid)
类看门狗:
#各种各样的init东西
def启动(自):
self.running=true
kids=['app1','app2','app3','app4','app5','app6','app7']
self.processs={}
儿童版:
自我启动儿童(儿童)
self.thread=threading.thread(目标=self.\u监视器)
self.thread.start()
自运行时:
时间。睡眠(10)
def start_子项(自身,名称):
尝试:
proc=subprocess.Popen(名称)
self.processs[name]=proc
除:
打印“哦,不”
其他:
打印“启动子项确定”
def_监视器(自身):
自运行时:
时间。睡眠(1)
如果自动运行:
对于kid,在self.processs.iteritems()中进行处理:
如果proc.poll()不是None:#进程结束
自我启动儿童(儿童)
因此,watchdog.start()将启动所有7个进程,如果我发送任何进程SIGTERM,它将结束,监视器线程将再次启动它。但是,如果我随后发送新进程SIGTERM,它将忽略它

我应该能够一次又一次地向重新启动的进程发送kill-15。为什么重新启动后会忽略它?

正如这里所解释的:当Python创建新线程时,它会阻止该线程(以及线程生成的任何进程)的所有信号

我用sigprocmask修复了这个问题,通过ctypes调用。这可能是也可能不是“正确”的方法,但它确实有效

在子进程中,在
\uuuuu init\uuuu
期间:

libc = ctypes.cdll.LoadLibrary("libc.so")
mask = '\x00' * 17 # 16 byte empty mask + null terminator 
libc.sigprocmask(3, mask, None) # '3' on FreeBSD is the value for SIG_SETMASK

在Python中恢复默认信号处理程序不是比通过ctypes更好吗?在子进程中,使用信号模块:

import signal
for sig in range(1, signal.NSIG):
    try:
        signal.signal(sig, signal.SIG_DFL)
    except RuntimeError:
        pass

尝试设置无法捕获的信号(如SIGKILL)时会引发RuntimeError。

因此,这似乎是由于在python线程中弹出进程造成的。根据,Python设置了一个信号掩码来阻止从线程启动的进程上的所有信号。该死的,Python?我现在尝试使用ctypes调用sigprocmask(),并将信号掩码重置为not block。混合使用fork/exec、线程和信号的任何两个都很难正确。将这三者混合在一起会导致灾难。我是否提到了看门狗进程本身是一个守护进程,它会多次分叉以分离自身?Python3.2现在计划了一个很好的灾难.sigprocmask():我正在编写一个测试工具,它运行服务器的多个实例(以及它自己的子进程)并测试它们之间的交互。你的回答救了我在纯python中做这件事。这不起作用,因为所有信号都被屏蔽了。无论您如何处理signal.signal(),进程都不会收到信号。我确实使用signal.signal()来设置SIGTERM的处理程序(这样我可以在退出时清理),但是您仍然需要使用sigprocmask来允许进程看到SIGTERM。@gdm:很抱歉,我不知道在Python中有什么方法可以做到这一点,所以通过ctype调用可能是唯一的方法。