如何从运行pyzmq的进程中捕获SIGERM,SIGINT?

时间:2015-08-05 04:29:37

标签: python signals zeromq pyzmq

我正在使用PYZMQ,似乎我不能再抓住SIGTERM了。为了优雅地处理SIGTERM,我该怎么做?

以下是代码段:

from time import sleep
from signal import signal, SIGTERM, SIGINT
from threading import Lock, Thread
try:
    import cPickle as pickle
except ImportError:
    import pickle
import zmq


zmq_poller = None

class server(Thread, object):
    def __init__(self, transport):
        self.context = zmq.Context()
        self.zmq_socket = self.context.socket(zmq.PULL)
        self.zmq_socket.setsockopt(zmq.RCVTIMEO, 2000)
        self.zmq_socket.bind(transport)
        self.keep_running = True
        Thread.__init__(self)

    def process_data(self, data):
        data = self.decode(data)

    def decode(self, data):
        return pickle.loads(data)

    def run(self):
        while self.keep_running:
            try:
                data = self.zmq_socket.recv()
                self.process_data(data)
            except zmq.error.Again:
                pass
            except zmq.error as e:
                print e

    def stop(self):
        self.keep_running = False

def handle_stop(signum=None, frame=None):
    if zmq_poller:
        zmq_poller.stop()

if __name__ == '__main__':
    signal(SIGTERM, handle_stop)
    signal(SIGINT, handle_stop)
    mc = server('ipc:///tmp/abc')
    zmq_poller = mc
    mc.setDaemon(True)
    mc.start()
    mc.join()
    sleep(100)

如我所见,如果我向进程发送SIGTERM,SIGINT,则不会调用handle_stop信号处理程序

1 个答案:

答案 0 :(得分:1)

您遇到问题的原因是您的主要帖子在threading.Thread.join Execution of Python signal handlers上被阻止了:

  

Python信号处理程序不会在低级(C)信号处理程序中执行。相反,低级信号处理程序设置一个标志,告诉虚拟机稍后执行相应的Python信号处理程序(例如,在下一个字节码指令处)

     

...

     

纯粹在C中实现的长时间运行计算(例如在大量文本上进行正则表达式匹配)可以在任意时间内不间断地运行,无论接收到任何信号。计算完成后将调用Python信号处理程序。

3.3之前的版本,signal模块绝对不会公开您自己解决此问题所需的工具。因此,如果您无法升级到3.3,则解决方案是等待可中断的内容,例如ConditionEvent。子线程在退出之前立即通知事件,主线程在它加入子线程之前等待事件。