从另一个线程关闭挂起的 zmq 套接字

Posted

技术标签:

【中文标题】从另一个线程关闭挂起的 zmq 套接字【英文标题】:closing hanging zmq socket from another thread 【发布时间】:2012-07-08 05:41:40 【问题描述】:

有没有什么方法可以在不破坏其他可能正在使用的套接字的情况下从 Python 中的另一个线程关闭特定挂起的 recv zmq 套接字?以下代码似乎没有退出;用ctx.destroy() 替换sock.close() 会导致它退出,但这显然会破坏上下文中的所有套接字:

import zmq
import time
import threading as th
ctx = zmq.Context()
sock = ctx.socket(zmq.ROUTER)
sock.bind('tcp://*:6000')
def shutdown():
    time.sleep(5)
    print 'closing'
    sock.close()
t = th.Thread(target=shutdown)
t.start()
try:
    sock.recv()
except zmq.ZMQError:
print 'closed'

【问题讨论】:

破坏上下文有时也会导致在控制台上打印Assertion failed 消息。 【参考方案1】:

一种可能性是在上下文管理器中执行套接字操作,该上下文管理器使用信号处理程序关闭套接字,该信号处理程序在检测到信号时引发异常:

import zmq
import signal, time
import threading as th
from contextlib import contextmanager
@contextmanager
def ZMQErrorOnAlarm():
    def handler(signum, frame):
        raise Exception('ALARM detected')
    signal.signal(signal.SIGALRM, handler)
    yield
ctx = zmq.Context()
sock = ctx.socket(zmq.ROUTER)
sock.bind('tcp://*:6000')
def shutdown():
    signal.alarm(5)
    print 'closing'
t = th.Thread(target=shutdown)
t.start()
with ZMQErrorOnAlarm():
    try:
        sock.send('x')
        sock.recv()
    except:
        print 'closed'

【讨论】:

可以通过将信号处理程序链接到适当的信号并使用os.kill(os.getpid(), signal_id)发送信号来使用其他信号

以上是关于从另一个线程关闭挂起的 zmq 套接字的主要内容,如果未能解决你的问题,请参考以下文章

多线程套接字连接挂起 c#。套接字超时/挂起

为啥 zmq 将多条消息打包到一个 TCP 帧中?

ZMQ之多线程编程

将 ZMQ 上下文传递给线程

ZeroMQ API 代理

每个单独的 TCP 套接字的多个挂起读取或多个挂起写入的性能优势?