Python中信号处理程序的执行上下文

4

我从这里了解到,当接收到信号时,exit_gracefully被调用,同时while True内部的代码也在运行。起初我以为处理程序在另一个线程中运行,所以我编写了一段代码来测试它:

import os
import signal
import threading

def sig_handler(signal_frame, num):
    print('handler PID: {}'.format(os.getpid()))
    print('current thread identity: {}'.format(threading.current_thread().ident))

signal.signal(signal.SIGTERM, sig_handler)

try:
    print('main execution PID: {}'.format(os.getpid()))
    print('current thread identity: {}'.format(threading.current_thread().ident))
    while True:
        time.sleep(5)
        print('Hello')
except KeyboardInterrupt:
    print('Good bye')

我运行了这段代码,首先发送了一个 SIGTERM 信号(使用 kill -SIGTERM pid 命令),然后发送了一个 SIGINT 信号。输出结果为:

main execution PID: 1002
current thread identity: 140284238558976
Hello
Hello
handler PID: 1002
current thread identity: 140284238558976
Hello
Hello
Good bye

您看到的一切都一样,但处理程序如何在与主代码完全相同的上下文中运行?它不应该在另一个线程中吗?
1个回答

3
您要寻找的答案在Python信号文档中:信号处理器一节,其中指出:

Python信号处理器总是在主线程中执行,即使该信号是在另一个线程中接收到的。

此外:

低级信号处理器会设置一个标志,告诉虚拟机在稍后执行相应的Python信号处理器。

因此,当接收到信号时,处理器不会与while循环中的代码同时执行。相反,执行您的代码的虚拟机将被告知尽快运行信号处理代码,在执行X个字节码指令后可能会运行,因此您的循环在处理程序代码运行时会暂停。稍作修改就可以演示这一点:

def sig_handler(signal_frame, num):
    print('handler PID: {}'.format(os.getpid()))
    print('current thread identity: {}'.format(threading.current_thread().ident))
    time.sleep(5) # we put a long delay here

signal.signal(signal.SIGTERM, sig_handler)

try:
    print('main execution PID: {}'.format(os.getpid()))
    print('current thread identity: {}'.format(threading.current_thread().ident))
    while True:
        time.sleep(1) # sleep less now
        print('Hello')
except KeyboardInterrupt:
    print('Good bye')

现在,当你发送SIGTERM信号时,你会注意到while循环的执行会暂停5秒钟。

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