php - 如果设置了 pcntl_signal(),我可以依赖在 SIGTERM 上调用的 register_shutdown_function() 吗?

标签 php signals exit pcntl

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

由于 Supervisor 更擅长确保只有指定数量的实例并行运行,我可以让它们运行更长时间。然而,这确实意味着我的进程更有可能接收到终止信号,要么是直接来自 kill,要么是因为它们已通过 Supervisor 停止。因此,我正在试验如何在 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 或其他终止信号,手册在这一点上非常清楚:

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 上工作也很有趣 - 我知道 ticks will be handled differently在 7.1 中,因此更有可能出现不同的行为。

最佳答案

PHP 用户关闭函数在普通进程终止期间被调用,有点类似于在其他编程语言中使用 atexit 注册的函数。显式 exit 或脚本末尾的隐式退出是普通进程终止。

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

当您使用 pcntl_signal 拦截 SIGTERM 时,您正在安装不同的行为并让您自己有机会体验普通的进程终止。

是的,您可以依赖这种行为。虽然主要的手册条目并不明确,但您引用的“注释”的其余部分如下:

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

关于php - 如果设置了 pcntl_signal(),我可以依赖在 SIGTERM 上调用的 register_shutdown_function() 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38419471/

相关文章:

php - 团队日程表的 MySQL 查询

python - 正弦信号与矩形脉冲的卷积

c++ - 如何在sigaction sa_sigaction中设置类方法?

c++ - 如何在 SIGSEGV 之后销毁在 main() 中创建的对象

java - 什么会导致 Java 在 System.exit() 之后继续运行?

Python运行系统命令然后退出...不会退出

php - Twitter Phirehose 主题标签搜索不起作用

php - 连接 4 个 MySQL 表

c - 未调用信号函数

php - 菜单页面状态