Python:什么是SIGTERM的默认处理方式?

48

如果Python收到一个SIGTERM信号,但没有为其注册信号处理程序,它默认会执行什么操作?


很抱歉地说,这里的赏金已经浪费了,因为没有任何变化,Thomas Wouters的答案对于当前Python版本(包括3.6和3.7)仍然是正确的 - Martijn Pieters
终止信号中断。 - Rachelle Rosenthal
3个回答

36

建立在Thomas Wouters的答案之上,Python没有为SIGTERM信号注册处理程序。我们可以通过执行以下操作来看到这一点:

In[23]: signal.SIG_DFL == signal.signal(signal.SIGTERM,signal.SIG_DFL)
Out[23]: True

这意味着系统将采取默认操作。在Linux上,根据信号手册,SIGTERM的默认操作是终止进程。

终止进程意味着:

  • 进程在执行代码时将不再被分配时间片。

    • 这意味着它将不会引发异常或调用try: finally:块中的代码或上下文管理器的__exit__方法。由于该特定Python解释器永远没有机会执行另一个指令,因此不会执行这些操作。
  • 进程的内存和其他资源(打开的文件、网络套接字等)将释放回系统的其他部分。


6
这是非常正确、重要,而且(至少对我来说)不太直观。我原本以为 finally 子句和上下文管理器的 exit 方法的整个目的在于确保代码总是运行(除了系统级别处理的 SIGKILL 之外)。我花了几天时间苦苦思考,直到现在才意识到你在回答中已经提出了这一点。我需要记住这一点。 - matlehmann

25

没有任何内容。Python本身不为该信号注册信号处理程序。您可以在交互式解释器中检查此功能:

>>> import signal
>>> signal.signal(signal.SIGTERM, signal.SIG_DFL)
0
>>> signal.SIG_DFL
0

这显示了signal.signal()对于signal.SIGTERM返回signal.SIG_DFL。与之对比的是signal.SIGINT,它具有默认信号处理程序(它会引发KeyboardInterrupt):

>>> signal.signal(signal.SIGINT, signal.SIG_DFL)
<built-in function default_int_handler>

7
这也意味着如果进程被 SIGTERM 终止,通过 atexit.register() 注册的函数将不会被调用。 - Sven Marnach
18
好的,但它具体是做什么呢?退出不干净?完全忽略它?还是其他什么操作? - Lucretiel
立即死亡。Python完全忽略了信号,因此立即死亡。Python什么也不做。这是我对上面人们所说的话的理解。如果我误解了,有人可以随时加入并纠正我。 - Hugh Perkins
(可能)然而,我们可以注册自己的处理程序来引发普通异常吗? - Hugh Perkins

1

看看这个例子:

import time

class A:
    def __init__(self):
        print("A.__init__()")

    def __del__(self):
        print("A.__del__()")

a = A()
b = A()

time.sleep(10)

在正常情况下,输出将是:


A.__init__()
A.__init__()
A.__del__()
A.__del__()

但是,如果您使用SIGTERM杀死它,则会收到以下消息:

A.__init__()
A.__init__()
Terminated

因此,程序没有正常终止(析构函数未被调用)。

是的,当进程没有注册SIGTERM处理程序时,这是默认操作。这就是Thomas Wouters的答案告诉我们的,而stochastic则明确说明了这一点。 - Martijn Pieters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接