出于某种原因,siginterrupt()似乎只能设置接收到的第一个信号的行为。
在这个示例程序中,第一个SIGQUIT看起来什么都不做,但第二个sigquit打印出“SIGQUIT Handler”,而s.accept()则抛出一个Interrupted系统调用exception。
from signal import * from socket import * import sys def sigquitHandler(signum, frame): print("SIGQUIT Handler") s = socket() s.bind(("0.0.0.0", int(sys.argv[1]))) s.listen(5) signal(SIGQUIT, sigquitHandler) siginterrupt(SIGQUIT, False) client, addr = s.accept() # Or any syscall that blocks client.close() s.close()
我在这里误解了什么?
编辑:这是其他东西,我不明白,在这个程序中,一个SIGQUIT中断select()。 这是否应该发生?
from signal import * import select import sys def sigquitHandler(signum, frame): print("SIGQUIT Handler") signal(SIGQUIT, sigquitHandler) siginterrupt(SIGQUIT, False) select.select([sys.stdin], [], [])
你正在使用哪个unix
? 在C
级,BSD和System 5(SYSV)的信号处理有不同的实现和语义。
我的猜测是你正在使用SYSV,在这种情况下,信号处理程序返回(经典信号处理)之后,信号处置被重置为SIG_DFL。 在SYSV上,您需要在处理程序中调用signal
来重新安装该处理程序。
Python或多或少地提供了BSD风格的信号处理。 因此,在SYSV OS上,Python必须通过signal
来管理信号处理程序的重新安装。 现在,根据python doco的siginterrupt
:
请注意,使用signal()安装信号处理程序将通过以给定信号的真实标志值隐式调用siginterrupt()来将重新启动行为重置为可中断。
如果 Python自动重新安装信号处理程序(为了提供类似于BSD的语义),它可能会以隐式方式调用siginterrupt(1)
。
当然,我的猜测可能是错的。
你可以通过像这样定义sigquitHandler来解决这个问题:
def sigquitHandler(signum, frame): print("SIGQUIT Handler") siginterrupt(SIGQUIT, False)
这取决于Python何时以及如何恢复信号配置。
编辑
在信号处理程序中添加siginterrupt(SIGQUIT, False)
没有任何影响。
编辑2
在Python2.6源代码中多了一些东西之后,清楚地知道这不仅仅是一个SYSV问题。 它也会影响BSD系统。
这是一个Python的错误 。 “siginterrupt with flag = False在收到信号时复位”,这在后面的python2.6版本中已经修复。 (2.6.6+,2.7+)
对于第二个,siginterrupt不影响select()。