为什么Python从&;开始时会忽略SIGINT;来自shell脚本?

为什么Python从&;开始时会忽略SIGINT;来自shell脚本?,python,signals,Python,Signals,在调试另一个脚本时,我发现如果Python是从带有&的shell脚本启动的,那么SIGINT的信号处理设置会更改为忽略它 x.py内容: import signal print(signal.getsignal(signal.SIGINT)) python3 x.py python3 x.py & noproblem.sh内容: import signal print(signal.getsignal(signal.SIGINT)) python3 x.py python3 x

在调试另一个脚本时,我发现如果Python是从带有
&
的shell脚本启动的,那么SIGINT的信号处理设置会更改为忽略它

x.py
内容:

import signal
print(signal.getsignal(signal.SIGINT))
python3 x.py
python3 x.py &
noproblem.sh
内容:

import signal
print(signal.getsignal(signal.SIGINT))
python3 x.py
python3 x.py &
问题.sh
内容:

import signal
print(signal.getsignal(signal.SIGINT))
python3 x.py
python3 x.py &
直接运行
x.py
时,直接使用
&
或通过
noproblem.sh
运行时,SIGINT的信号处理程序是默认的
信号。默认的int处理程序
,负责引发键盘中断:

07:14 ~ $ python3 x.py
<built-in function default_int_handler>
07:14 ~ $ python3 x.py &
[1] 126909
07:14 ~ $ <built-in function default_int_handler>

[1]+  Done                    python3 x.py
07:14 ~ $ bash noproblem.sh
<built-in function default_int_handler>

我找不到任何文档来解释为什么会发生这种情况。政府没有提到这种行为。这是故意的,还是一个bug?

进一步挖掘之后,我终于找到了原因

首先,如果Python从其父进程继承了操作系统级别的SIG_IGN for SIGINT设置,则不会安装默认的SIGINT处理程序。它仅在继承SIG_DFL设置时安装该处理程序。我们可以在
信号
模块的中看到这一点:

IntHandler=PyDict_GetItemString(d,“默认的int_处理程序”);
如果(!IntHandler)
后藤最后;
Py_增量(IntHandler);
_Py_原子_存储_已松弛(&处理程序[0]。已跳闸,0);
对于(i=1;i
第二,shell脚本在默认情况下在禁用作业控制的情况下运行,并且在禁用作业控制时以
&
启动的进程继承SIGINT和SIGQUIT的SIG\u-IGN设置。引述:

如果在shell执行异步列表时禁用了作业控制(请参见set-m的说明),则列表中的命令将从shell继承SIGINT和SIGQUIT信号的忽略信号动作(SIG_IGN)

在shell脚本中,我找不到明确的标准引用,说默认情况下禁用了作业控制,只说默认情况下,交互式shell启用了作业控制(模糊地表示非交互式shell的相反设置):

-m

如果实现支持用户可移植性实用程序选项,则应支持此选项。所有作业应在其各自的过程组中运行。后台作业完成后,在shell发出提示之前,应将报告后台作业退出状态的消息写入标准错误。如果前台作业停止,shell将向标准错误写入一条消息,按照作业实用程序的描述进行格式化。此外,如果作业改变状态而不是退出(例如,如果作业停止输入或输出或被SIGSTOP信号停止),外壳应在写入下一个提示之前立即写入类似的消息此选项默认情况下对交互式Shell启用。


shell中的
&
将为任务创建的新进程发送到后台。后台进程不接收信号。@MYousefi:后台进程完全能够接收信号,尽管它们在与前台进程相同的环境中可能接收不到相同的信号。请注意,您的解释不会解释为什么手动运行
python3 x.py&
会显示默认处理程序,或者如果只是信号是否被接收的问题,为什么这些都会影响Python自己的信号处理设置。也许可以帮到忙。