python - 在基于 Gevent 的应用程序中捕获 TERM 信号

标签 python signals daemon gevent

我用基于 Gevent 的 Python 编写了一个简单的守护进程。守护进程在存在之前需要做一些清理,因此它有必要处理 TERM 信号,执行清理并优雅地退出。在不基于 Gevent 的单线程守护进程中,我使用 Python 的信号模块为 TERM 信号设置信号处理程序。信号处理程序抛出一个用户定义的异常,称为 TermSignal。守护进程的主线程可以捕获 TermSignal 异常,进行清理并退出。

当我尝试在基于 Gevent 的守护进程中实现该解决方案时,它没有按预期工作。守护进程有一个主要的 greenlet,它调用 worker greenlet 上的 joinalljoinall 调用包含在 try/except block 中,该 block 捕获 KeyboardInterrupt,这允许守护进程在运行时执行清理,而无需守护进程。但是,当我实现上述解决方案并向进程发送 TERM 信号时,我可以在控制台窗口中看到其中一个工作人员 greenlet 引发了 TermSignal 异常,而不是主 greenlet。尽管我调用 joinall 并将 raise_error 参数设置为 True,但这个未捕获的异常并没有传播到主 greenlet。结果是其中一个 worker greenlets 由于异常而崩溃,但是守护进程根本没有退出。

最佳答案

经过一番搜索,我找到了解决方案。如前所述 here , Gevent 的猴子补丁不会给 Python 内置的 signal.signal 函数打补丁。为了让我的解决方案起作用,主要的 greenlet 必须调用 gevent.signal 而不是 signal.signal 来设置处理程序。此外,gevent.signal 需要不接受任何参数的处理函数,而 signal.signal 需要接受 2 个参数的处理函数。因为无论如何我都不关心这些参数,所以我将术语处理程序更改为如下所示:

def _term_handler(*_):
    raise TermSignal()

以便在 Gevent 应用程序和常规 Python 应用程序中可以使用相同的术语 handle。尽管在两种情况下都可以使用相同的处理程序,但需要通过适当的函数(signal.signalgevent.signal)进行设置

关于python - 在基于 Gevent 的应用程序中捕获 TERM 信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20630142/

相关文章:

python - 使用 unittest discover 传递参数(对于 argparse)

python - 使用 zeep/python 创建 XML 序列

带参数调用Linux服务

Python线程/守护进程

Linux 守护进程停止启动停止守护进程

python - 将像素值显示为图像

python - 使用 ElementTree 在 python 中解析 xml

c++ - 多线程定时器类

c - C中的多个警报?

c - 忽略 SIGQUIT 一次