我复制了以下代码片段,以重现我在处理SIGTERM处理程序时遇到的问题-
具有SIGTERM处理程序的主进程。
从主进程产生的线程
从上述线程产生的子进程
目的是要了解SIGTERM处理程序的工作原理。我假设SIGTERM处理程序将由生成的线程以及进程继承。有一个部分发生死锁(因为未读取共享队列)。由于存在死锁,因此可以使所有进程和线程保持活动状态。
from multiprocessing import Process, Queue
from threading import Thread
import os
import sys
import signal
def sigtermHandlerNew():
print "SIGTERM received for process: {}".format(os.getpid())
sys.exit()
def f(q):
print "f proc id: {}".format(os.getpid())
q.put('X' * 1000000)
def proc_starter():
queue = Queue()
p = Process(target=f, args=(queue,))
p.start()
p.join() # this deadlocks
obj = queue.get()
def main():
signal.signal(signal.SIGTERM, sigtermHandlerNew)
print "main process id: {}".format(os.getpid())
t = Thread(target=proc_starter)
t.start()
t.join()
main()
运行此程序后,将运行2个进程。我在这里观察到一个奇怪的行为-当我尝试使用SIGTERM($ kill -15 <proc-id>
)杀死任何进程时,我发现SIGTERM处理程序的功能没有被调用,并且这个死锁一直存在(直到我通知SIGKILL)>
有人可以帮助我理解为什么流程未兑现信号的原因。您可以直接运行此代码段。
答案 0 :(得分:1)
Python 2在混合线程和信号时遇到许多问题,通常不建议这样做。您可以在官方documentation中阅读有关此方面的信息。
更深入地讲,影响您的是,在Python 2中,使用基本锁的多个原语不能被信号issue中断。
此问题不再影响Python 3,因此我强烈建议您切换到较新版本的解释器。
如果您不能这样做,一种解决方法是将超时设置为阻止操作,例如Queue.get
。