php – 如果pcntl_signal()被设置,我可以依靠在SIGTERM上调用register_shutdown_function()吗?

我正在处理一个定期称为后台进程的应用程序。其中一个被cron叫,但是我正在寻找更强大的东西,所以将其转换为在主管下运行。 (它可能会运行10分钟,在此期间它可以检测到工作要做或空闲,一旦退出,主管将自动重新生成一个干净的实例。)

由于主管更好地确保只有指定数量的某些事件的并行运行,我可以远离运行更长时间。这的确意味着我的进程更有可能接收终止信号,无论是直接杀死,还是因为已经通过主管停止。因此,我正在尝试如何在PHP中处理这个问题。

看起来基本的解决方案是使用pcntl_signal()像这样:

declare(ticks = 1);
pcntl_signal(SIGTERM, 'signalHandler');
pcntl_signal(SIGINT, 'signalHandler');

function signalHandler($signal) {
    switch($signal) {
        case SIGTERM:
        case SIGINT:
            echo "Exiting now...\n";
            exit();
    }
}

但是,我的代码中有几点可以仔细关闭处理。一种方法是使一个处理程序调用这些各种东西,但它需要一些重构,我想避免。替代方法是在我需要的地方添加pcntl_signal(),但不幸的是,它似乎只能一次安装一个处理程序。

然而,看起来我可能能够使用register_shutdown_function().这不会自己陷阱^ C或其他终止的sig,手册在这一点上是很清楚的:

Shutdown functions will not be executed if the process is killed with a SIGTERM or SIGKILL signal

令人惊讶的是,我发现如果我使用pcntl_signal()来做一个退出,那么关闭处理程序确实被调用。此外,由于可以有许多关机处理程序,这很好地解决了我的问题 – 我的代码中希望处理终止的每个类都可以捕获和管理自己的关机。

我最初的问题是,为什么这样做?我已经尝试注册一个没有信号处理程序的关机功能,这似乎没有被调用,正如手册所说。我猜这个过程是由PHP保存的,以处理信号,这会导致关闭处理程序被调用?

此外,我可以依靠这种行为,当手册对此有所怀疑吗?我正在使用PHP 5.5,而且还没有希望升级到PHP7。所以我会感兴趣的是5.5和5.6,在各种发行版上。

当然,如果(或不会)在7.0和/或7.1上工作,那也是有趣的 – 我知道7.1中的ticks will be handled differently,所以有更多的机会有不同的行为。

在普通过程终止期间调用PHP用户关机功能,有些类似于在其他编程语言中用atexit注册的功能。脚本结尾处的显式退出或隐式退出是一个普通的进程终止。

然而,信号死亡是异常进程终止。 SIGTERM的默认行为(以及SIGKILL的强制性行为)是立即终止运行过程,而不运行任何清理处理程序。

当您使用pcntl_signal拦截SIGTERM时,您正在安装不同的行为,并为您提供体验普通过程终止的机会。

是的,你可以依靠这个行为。虽然主要手册条目不明确,但您引用的其他“注释”则为:

[Y]ou can use pcntl_signal() to install a handler for a SIGTERM which uses exit() to end cleanly.

翻译自:https://stackoverflow.com/questions/38419471/can-i-rely-on-register-shutdown-function-being-called-on-sigterm-if-pcntl-sig

转载注明原文:php – 如果pcntl_signal()被设置,我可以依靠在SIGTERM上调用register_shutdown_function()吗?