为什么signal.pause()会阻止套接字断开?

时间:2018-06-12 21:57:53

标签: python sockets signals python-multiprocessing

我使用Python 3.5和multiprocessing模块处理套接字并遇到意外行为。我的程序本质上是一些运行的线程,直到客户端收到某条消息告诉它停止。

如果我像这样执行它,我会得到一个BrokenPipeError来破坏程序,尽管while True循环和except阻止。

#!/usr/bin/env python3
import signal
import traceback
from multiprocessing.dummy import Pool
from process import Process

def main():
    while True:
        try:
            # a Process has a couple threads
            process = Process()
            listener_pool = Pool(processes=1)
            sender_pool = Pool(processes=1)

            # blocking socket client that runs forever
            listener_pool.apply_async(process.listener_thread.run, ())

            # blocking socket server that runs forever
            sender_pool.apply_async(process.sender_thread.run, ())

            return 0

        except BrokenPipeError:
            traceback.print_exc()

            # closing connections
            process.emitter_thread.socket.close()
            process.listener_thread.socket.close()

if __name__ == '__main__':
    main()

但是,当我在返回之前添加signal.pause()权限时,不仅代码按预期运行,而且任何时候都不会引发BrokenPipeError

#!/usr/bin/env python3
import signal
import traceback
from multiprocessing.dummy import Pool
from process import Process

def main():
    while True:
        try:
            # a Process has a couple threads
            process = Process()
            listener_pool = Pool(processes=1)
            sender_pool = Pool(processes=1)

            # blocking socket client that runs forever
            listener_pool.apply_async(process.listener_thread.run, ())

            # blocking socket server that runs forever
            sender_pool.apply_async(process.sender_thread.run, ())
            signal.pause()
            return 0

        except BrokenPipeError:
            traceback.print_exc()

            # closing connections
            process.emitter_thread.socket.close()
            process.listener_thread.socket.close()


if __name__ == '__main__':
    main()

根据docs,信号只能由主线程处理,但两个套接字都由辅助线程处理。 signal.pause()做什么来防止套接字在同一个上下文中被调用时被破坏?

1 个答案:

答案 0 :(得分:1)

apply_async,正如其名称所暗示的那样立即返回。因此,在程序的第一个版本中,主线程在启动子线程时退出(虚拟进程只是threads using the multiprocessing api)。

因此主线程在异常发生之前很久就退出try块。

在第二种情况下,signal.pause()强制主线程在try块中等待,它将捕获异常。

请注意,这是一个脆弱的解决方案,因为接收任何信号将使signal.pause()恢复并且主线程退出。