siginterrupt()仅适用于第一个信号? (蟒蛇)

时间:2009-11-02 22:41:35

标签: python linux unix signals

出于某种原因,siginterrupt()似乎只设置接收到的第一个信号的行为。

在这个示例程序中,第一个SIGQUIT似乎什么都不做,但第二个sigquit打印“SIGQUIT Handler”和s.accept()会引发中断的系统调用异常。

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], [], [])

2 个答案:

答案 0 :(得分:4)

这是python的bug。 “siginterrupt with flag = False在收到信号时被重置”,这已在后来的python2.6版本中得到修复。 (2.6.6 +,2.7 +)

对于第二个,siginterrupt不影响select()。

请参阅http://lkml.org/lkml/2005/7/23/119

答案 1 :(得分:2)

您使用的是哪个unix?在C级别,BSD与System 5(SYSV)上的信号处理有不同的实现和语义。

我的猜测是你正在使用SYSV,在这种情况下,信号处理器返回后信号处理被重置为SIG_DFL(经典信号处理)。在SYSV上,您需要在处理程序中调用signal以重新安装该处理程序。

Python或多或少提供了BSD风格的信号处理。因此,在SYSV OS上,Python必须通过signal管理信号处理程序的重新安装。现在,根据用于siginterrupt的Python doco:

  

请注意安装信号处理程序   with signal()将重置重启   被中断的行为   隐式调用siginterrupt()   给定的真实标志值   信号。

然后你去 - 如果 Python会自动重新安装你的信号处理程序(提供类似语义的BSD),它可能会以隐式调用siginterrupt(1)的方式这样做。 / p>

当然,我的猜测可能是错的。

可能能够通过定义sigquitHandler来解决此问题:

def sigquitHandler(signum, frame):
    print("SIGQUIT Handler")
    siginterrupt(SIGQUIT, False)

这取决于Python何时以及如何恢复信号处理。

修改

siginterrupt(SIGQUIT, False)添加到信号处理程序没有任何影响。

编辑2

在Python2.6源代码中进行了一些讨论之后,它清楚地表明这不仅仅是一个SYSV问题。它也会影响BSD系统。