php 信号没有立即处理
php signal not handled right away
我有一个用 PHP 编写的软件可以 运行 很长时间,它是通过命令行启动的(不是网络应用程序)。我想确保在软件退出时调用函数,包括通过 ctrl+c 终止时。当被信号杀死时,关闭函数(通过 register_shutdown_fucntion() 注册的析构函数和函数)不会被调用。
经过一些阅读,我意识到我必须在每个相关信号上添加一个处理程序才能调用 "exit;"。这样做解决了我的问题并且有效。
我的问题是,在某些情况下,信号没有立即得到处理。它可能需要几秒钟、几分钟,在某些情况下,根本没有得到处理。就像从未达到处理程序代码一样。我真的不知道从哪里开始调试它。我已经尝试过其他信号(sigkill、sighup 等),同样的行为。
我的代码在这些括号内
declare(ticks=1)
{...}
我找不到立即治疗和不立即治疗的时间之间的任何相关性。
如有任何帮助,我们将不胜感激。
信号应该这样处理:
首先,你必须像这样制作一个信号处理程序:
function signalHandler($signo = null) {
$pid = posix_getpid();
switch ($signo) {
//case SIGKILL: // you can't override SIGKILL so it is useless
case SIGTERM:
case SIGINT:
// unexpected shut down
exit(3);
break;
case SIGCHLD:
case SIGHUP:
// just ignore it
break;
case 10:
// user signal 1 received. Process exited normally
exit(0);
break;
case 12:
// user signal 2 received. Precess exited with a catched error
exit(3);
break;
default:
// ignore other signals
}
}
然后,在您的主进程中,您必须告诉 PCNTL 您正在使用此处理程序:
pcntl_signal(SIGTERM, "signalHandler");
pcntl_signal(SIGINT, "signalHandler");
// pcntl_signal(SIGKILL, "signalHandler"); // you can't override SIGKILL so it is useless
pcntl_signal(SIGCHLD, "signalHandler");
pcntl_signal(SIGHUP, "signalHandler");
pcntl_signal(10, "signalHandler");
pcntl_signal(12, "signalHandler");
我正在使用它,似乎同时适用于 200 个进程,8 个进程 运行,每个进程 10 秒。
这里,当一个进程退出时,他使用posix_kill($pid, 10)
发送信号10或12(表示成功或错误)
我认为这里的问题是,您可能调用了一个包含循环的函数,并且循环的每次迭代都需要花费大量时间(例如,从数据库中获取数据)。在这种情况下,当您的程序收到停止信号时,它会将此信号添加到堆栈,等待,直到从数据库中获取数据,然后调用信号处理函数。
我也在寻找一种立即调用信号处理函数的方法。也许PHP只是没有这个选项。
更新:
我想我找到了解决办法。尝试将 false
作为第三个参数传递给函数 pcntl_signal()
,如下所示:
pcntl_signal(SIGINT, function () {
echo 'Do something here.';
}, false);
我有一个用 PHP 编写的软件可以 运行 很长时间,它是通过命令行启动的(不是网络应用程序)。我想确保在软件退出时调用函数,包括通过 ctrl+c 终止时。当被信号杀死时,关闭函数(通过 register_shutdown_fucntion() 注册的析构函数和函数)不会被调用。
经过一些阅读,我意识到我必须在每个相关信号上添加一个处理程序才能调用 "exit;"。这样做解决了我的问题并且有效。
我的问题是,在某些情况下,信号没有立即得到处理。它可能需要几秒钟、几分钟,在某些情况下,根本没有得到处理。就像从未达到处理程序代码一样。我真的不知道从哪里开始调试它。我已经尝试过其他信号(sigkill、sighup 等),同样的行为。
我的代码在这些括号内
declare(ticks=1)
{...}
我找不到立即治疗和不立即治疗的时间之间的任何相关性。
如有任何帮助,我们将不胜感激。
信号应该这样处理: 首先,你必须像这样制作一个信号处理程序:
function signalHandler($signo = null) {
$pid = posix_getpid();
switch ($signo) {
//case SIGKILL: // you can't override SIGKILL so it is useless
case SIGTERM:
case SIGINT:
// unexpected shut down
exit(3);
break;
case SIGCHLD:
case SIGHUP:
// just ignore it
break;
case 10:
// user signal 1 received. Process exited normally
exit(0);
break;
case 12:
// user signal 2 received. Precess exited with a catched error
exit(3);
break;
default:
// ignore other signals
}
}
然后,在您的主进程中,您必须告诉 PCNTL 您正在使用此处理程序:
pcntl_signal(SIGTERM, "signalHandler");
pcntl_signal(SIGINT, "signalHandler");
// pcntl_signal(SIGKILL, "signalHandler"); // you can't override SIGKILL so it is useless
pcntl_signal(SIGCHLD, "signalHandler");
pcntl_signal(SIGHUP, "signalHandler");
pcntl_signal(10, "signalHandler");
pcntl_signal(12, "signalHandler");
我正在使用它,似乎同时适用于 200 个进程,8 个进程 运行,每个进程 10 秒。
这里,当一个进程退出时,他使用posix_kill($pid, 10)
我认为这里的问题是,您可能调用了一个包含循环的函数,并且循环的每次迭代都需要花费大量时间(例如,从数据库中获取数据)。在这种情况下,当您的程序收到停止信号时,它会将此信号添加到堆栈,等待,直到从数据库中获取数据,然后调用信号处理函数。
我也在寻找一种立即调用信号处理函数的方法。也许PHP只是没有这个选项。
更新:
我想我找到了解决办法。尝试将 false
作为第三个参数传递给函数 pcntl_signal()
,如下所示:
pcntl_signal(SIGINT, function () {
echo 'Do something here.';
}, false);