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

Ian*_*n P 7 python unix linux signals

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

在这个示例程序中,第一个SIGQUIT似乎什么也不做,但是第二个sigquit打印"SIGQUIT Handler"和s.accept()会抛出一个Interrupted系统调用异常.

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()
Run Code Online (Sandbox Code Playgroud)

我在这里误会了什么?


编辑:这是我无法弄清楚的其他东西,在这个程序中,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], [], [])
Run Code Online (Sandbox Code Playgroud)

mha*_*wke 2

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

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

Python 或多或少提供了 BSD 风格的信号处理。因此,在 SYSV 操作系统上,Python 必须通过signal. 现在,根据 Python doco for siginterrupt

请注意,使用 signal() 安装信号处理程序将通过使用给定信号的 true 标志值隐式调用 siginterrupt() 将重新启动行为重置为可中断。

就这样 -如果Python 自动重新安装信号处理程序(以提供类似 BSD 的语义),它很可能会以隐式调用siginterrupt(1).

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

可以通过如下定义 sigquitHandler 来解决此问题:

def sigquitHandler(signum, frame):
    print("SIGQUIT Handler")
    siginterrupt(SIGQUIT, False)
Run Code Online (Sandbox Code Playgroud)

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

编辑

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

编辑2

在对 Python2.6 源代码进行了更多研究之后,很明显这不仅仅是 SYSV 问题。它也会影响 BSD 系统。