为什么 signal.pause() 会阻止套接字损坏?

Why does signal.pause() stop sockets from breaking?

我在使用 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() 做了什么来防止套接字损坏,甚至没有在同一上下文中调用它们?

apply_async, as its name suggests returns immediately. Therefore in the first version of your program, the main thread exits right as it starts the child threads (dummy processes are just threads using the multiprocessing api).

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

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

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