有一种情况是在启动时 未 安装默认的sigint处理程序,也就是在程序启动时包含信号掩码SIG_IGN
for的SIGINT
情况。可以在这里找到负责此操作的代码。
被忽略信号的信号掩码从父进程继承,而已处理信号重置为SIG_DFL
。因此,在这种情况下,如果SIGINT
忽略了if (Handlers[SIGINT].func == DefaultHandler)
源中的条件不会触发并且未安装默认处理程序的情况,则python不会覆盖父进程所做的设置。
因此,让我们尝试显示不同情况下使用的信号处理程序:
# invocation from interactive shell
$ python -c "import signal; print(signal.getsignal(signal.SIGINT))"
<built-in function default_int_handler>
# background job in interactive shell
$ python -c "import signal; print(signal.getsignal(signal.SIGINT))" &
<built-in function default_int_handler>
# invocation in non interactive shell
$ sh -c 'python -c "import signal; print(signal.getsignal(signal.SIGINT))"'
<built-in function default_int_handler>
# background job in non-interactive shell
$ sh -c 'python -c "import signal; print(signal.getsignal(signal.SIGINT))" &'
1
因此,在最后一个示例中,SIGINT
将其设置为1(SIG_IGN
)。这与在Shell脚本中启动后台作业时相同,因为默认情况下它们是非交互式的(除非您-i
在shebang中使用该选项)。
因此,这是由外壳程序在非交互式外壳程序会话中启动后台作业时忽略信号引起的,而不是由python直接引起的。至少bash
与dash
这样的行为,我没有尝试过其他炮弹。
有两种方法可以处理这种情况:
手动安装默认信号处理程序:
import signal
signal.signal(signal.SIGINT, signal.default_int_handler)
将-i
选项添加到shell脚本的shebang中,例如:
#!/bin/sh -i
编辑:bash手册中记录了此行为:
信号 … 当作业控制无效时,除了这些继承的处理程序之外,异步命令还会忽略SIGINT和SIGQUIT。