简体   繁体   English

使用Python Interrupting Select中的信号处理程序的乐趣

[英]Fun with Signal Handlers in Python Interrupting Select

I'm working on a programming project--writing a basic P2P filesharing application in Python. 我正在编写一个编程项目 - 用Python编写一个基本的P2P文件共享应用程序。 I'm using two threads: a main one to call select and wait for input from a list of sockets and sys.stdin (to receive typed commands) and a helper thread that takes status update messages off a queue and prints them. 我正在使用两个线程:一个主要调用select并等待来自套接字列表和sys.stdin(接收类型命令)的输入,以及一个从队列中获取状态更新消息并打印它们的辅助线程。 (It is the only thing that prints anything) (这是打印任何东西的唯一东西)

I'm also required to catch the standard SIGINT and handle it to exit gracefully. 我还需要捕获标准的SIGINT并处理它以优雅地退出。 I have a quit method that does this; 我有一个退出方法,这样做; typing 'quit' as a command works just fine. 输入'quit'作为命令工作得很好。 So in the main thread I try setting this method as the handler for SIGINT. 所以在主线程中我尝试将此方法设置为SIGINT的处理程序。 As far as I can tell, the process catches the signal and calls the quit method. 据我所知,该过程捕获信号并调用quit方法。 The helper thread prints a message confirming that it is exiting. 帮助程序线程打印一条消息,确认它正在退出。 But then I get the following error message from the main thread: 但后来我从主线程中收到以下错误消息:

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')

After which the program does still exit. 之后程序仍然退出。 Whereas without the signal handler in place, sending a SIGINT gives me the following: 而没有信号处理程序,发送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

Which fails to terminate the program; 哪个未能终止该计划; I have to stop and kill it. 我必须停下来杀了它。 This is confusing because the SIGINT appears to interrupt the call to select only when it is caught by my custom method. 这很令人困惑,因为SIGINT似乎只在我的自定义方法捕获时才会中断调用。 (Which only puts a message on the print queue and sets a "done" variable) Does anyone know how this can be happening? (只在打印队列上放置一条消息并设置“完成”变量)有谁知道这是怎么回事? Is it just a bad idea trying to use signal handlers and threads simultaneously? 尝试同时使用信号处理程序和线程是一个坏主意吗?

I'm not sure about using signal handlers to catch this case, but I've found a recipe for handling this case on *nix based systems here: http://code.activestate.com/recipes/496735-workaround-for-missed-sigint-in-multithreaded-prog/ 我不确定是否使用信号处理程序来捕捉这种情况,但我在这里找到了基于* nix的系统处理这种情况的方法: http//code.activestate.com/recipes/496735-workaround-for-错过-SIGINT式多线程-PROG /

In a nutshell (If I undertand correctly): 简而言之(如果我正确地说):

Before you start any new threads, fork a child process (using os.fork ) to finish the program run, and have the parent process watch for the KeyboardInterrupt . 在开始任何新线程之前,派生子进程(使用os.fork )完成程序运行,并让父进程监视KeyboardInterrupt

When the parent catches the keyboard interrupt, you can kill the child process (which by now may have started other threads) using os.kill . 当父级捕获键盘中断时,您可以使用os.kill子进程(现在可能已启动其他线程)。 This will, in turn, terminate any threads of that child process. 反过来,这将终止该子进程的任何线程。

Yes, last night after I stopped working on it I realized that I did want it to interrupt. 是的,昨晚我停止工作后,我意识到我确实希望它能够中断。 It was being interrupted by executing the signal handler, presumably. 据推测,它正在被执行信号处理程序中断。 So I just catch the select.error and have it jump to the end of the loop, where it immediately exits and moves on to the cleanup code. 所以我只是捕获select.error并让它跳转到循环的末尾,它会立即退出并继续执行清理代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM