有趣的信号处理程序在Python中断选择



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

还需要捕获标准SIGINT并处理它以优雅地退出。我有一个quit方法来做这个;输入"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杀死子进程(现在可能已经启动了其他线程)。这将依次终止该子进程的所有线程。

是的,昨晚我停止工作后,我意识到我确实想让它中断。它可能是被执行信号处理程序中断的。所以我只捕获select。错误,并让它跳转到循环的末尾,在那里它立即退出,并继续执行清理代码。

最新更新