且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

python subprocess.call 不能正确处理信号

更新时间:2023-02-15 22:15:21

如果 wait 被中断,python 3.3 subprocess.call 实现会向其子进程发送 SIGKILL,它是由您的 Ctrl-C(SIGINT -> KeyboardInterrupt 异常)决定的.

The python 3.3 subprocess.call implementation sends a SIGKILL to its child if its wait is interrupted, which it is by your Ctrl-C (SIGINT -> KeyboardInterrupt exception).

因此,您会看到处理终端的 SIGINT(发送到整个进程组)的子进程与父进程的 SIGKILL 之间的竞争.

So, you see a race between the child process handling the terminal's SIGINT (sent to the whole process group) and the parent's SIGKILL.

来自 python 3.3 源代码,为简洁起见进行了

From the python 3.3 sources, edited for brevity:

def call(*popenargs, timeout=None, **kwargs):
    with Popen(*popenargs, **kwargs) as p:
        try:
            return p.wait(timeout=timeout)
        except:
            p.kill()
            p.wait()
            raise

将此与 python 2 实现进行对比:

Contrast this with the python 2 implementation:

def call(*popenargs, **kwargs):
    return Popen(*popenargs, **kwargs).wait()

多么令人不快的惊喜.当 waitcall 接口被扩展以适应超时时,这种行为似乎是在 3.3 中引入的.我认为这不正确,我已经提交了一个错误.

What an unpleasant surprise. It appears that this behavior was introduced in 3.3 when the wait and call interfaces were extended to accommodate a timeout. I don't find this correct, and I've filed a bug.