【问题标题】:Python: What is the default handling of SIGTERM?Python:SIGTERM 的默认处理是什么?
【发布时间】:2012-04-13 09:45:45
【问题描述】:

如果 Python 接收到 SIGTERM 但没有为其注册信号处理程序,默认情况下会在幕后做什么?

【问题讨论】:

  • 很抱歉,这里的赏金被浪费了,因为 没有改变 并且 Thomas Wouters 的回答对于当前的 Python 版本仍然正确,包括3.6 和 3.7。
  • 终止信号中断。

标签: python signals sigterm


【解决方案1】:

基于 Thomas Wouters 的回答,python 没有为 SIGTERM 信号注册处理程序。我们可以这样做:

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

这意味着系统将采取默认操作。在 linux 上,SIGTERM 的默认操作(根据the signal man page)是终止进程。

终止进程意味着:

  • 进程将不再被分配任何可以执行代码的时间片。

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

【讨论】:

  • 这是如此真实、重要且 - 至少对我而言 - 不直观。我认为 finally 子句和上下文管理器的 _exit_ 方法的全部工作是确保有问题的代码始终运行(除了 SIGKILL,我知道它是在系统级别处理的)。为此苦苦挣扎了几天,直到现在才意识到您已经在答案中提出了。我需要记住这一点。
【解决方案2】:

什么都没有。 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>

【讨论】:

  • 这也意味着如果进程被SIGTERM终止,通过atexit.register()注册的函数将不会被调用。
  • 好吧,但它有什么作用?不干净地退出?完全无视?还有什么?
【解决方案3】:

看这个例子:

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 的回答已经告诉我们的内容,并且随机指标明确了这一点。
猜你喜欢
  • 2019-01-18
  • 1970-01-01
  • 2012-07-25
  • 1970-01-01
  • 2013-03-22
  • 2013-06-15
  • 1970-01-01
  • 2015-06-09
  • 2022-08-18
相关资源
最近更新 更多