python - 在 Python 中断选择中使用信号处理程序很有趣

标签 python multithreading signals

我正在从事一个编程项目——用 Python 编写一个基本的 P2P 文件共享应用程序。我正在使用两个线程:一个主线程调用 select 并等待来自套接字和 sys.stdin 列表的输入(以接收键入的命令),另一个辅助线程从队列中获取状态更新消息并打印它们。 (这是唯一可以打印任何东西的东西)

我还需要捕获标准 SIGINT 并处理它以正常退出。我有一个 quit 方法可以做到这一点;输入“退出”作为命令就可以了。所以在主线程中,我尝试将此方法设置为 SIGINT 的处理程序。据我所知,进程捕获信号并调用 quit 方法。辅助线程打印一条消息,确认它正在退出。但随后我从主线程收到以下错误消息:

Traceback (most recent call last):
  File "peer.py", line 226, in <module>
    main()
  File "peer.py", line 223, in main
    p.run()
  File "peer.py", line 160, in run
    readables, writables, exceptions = select(self.sockets, [], [])
select.error: (4, 'Interrupted system call')

之后程序仍然退出。如果没有适当的信号处理程序,发送 SIGINT 会给我以下信息:

Traceback (most recent call last):
  File "peer.py", line 225, in <module>
    main()
  File "peer.py", line 222, in main
    p.run()
  File "peer.py", line 159, in run
    readables, writables, exceptions = select(self.sockets, [], [])
KeyboardInterrupt

未能终止程序;我必须停下来杀死它。这令人困惑,因为 SIGINT 似乎仅在我的自定义方法捕获时才中断对 select 的调用。 (它只在打印队列中放置一条消息并设置一个“完成”变量)有谁知道这是怎么发生的?尝试同时使用信号处理程序和线程只是一个坏主意吗?

最佳答案

我不确定是否使用信号处理程序来捕获这种情况,但我在这里找到了在基于 *nix 的系统上处理这种情况的方法:http://code.activestate.com/recipes/496735-workaround-for-missed-sigint-in-multithreaded-prog/

简而言之(如果我理解正确的话):

在启动任何新线程之前,派生一个子进程(使用 os.fork)以完成程序运行,并让父进程监视 KeyboardInterrupt

当父进程捕捉到键盘中断时,您可以使用 os.kill 终止子进程(此时它可能已经启动了其他线程)。反过来,这将终止该子进程的所有线程。

关于python - 在 Python 中断选择中使用信号处理程序很有趣,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7775368/

相关文章:

使用 signal_connect 在 C 中更改 GTK 标签

python - 在Python中从给定的 double 中获取第n个 double

python - 在 Python 中从大型字典中获取前 3 个最高值的快速有效方法是什么?

java - 如何在后台线程中正确执行SQL查询?

java - 当使用RabbitMQ作为java工作队列时,应该如何处理并发和 transient 错误?

.net - 在多线程期间检索 Windows 窗体属性

c++ - 在信号处理程序中使用长数据。

python - 从小部件到小部件的自定义信号

python - 如何将函数的文档字符串放入变量中?

Python:当旧对象与新对象相等时复制对象