我正在编写一个守护进程,它周期性地做一些工作并在再次重复之前休眠一段时间。但它在睡眠时仍必须对外部影响(即终止请求)做出响应。
我设法用 ALRM 信号实现睡眠超时并用 TERM 信号终止(示例):
// ...
declare(ticks = 1);
function do_work()
{
echo "Doing some work.\n";
}
$term = FALSE;
$sighandler = function ($signal) use (&$term)
{
if ($signal === SIGTERM)
{
pcntl_alarm(0);
$term = TRUE;
echo "TERM HANDLER\n";
} else {
echo "ALRM HANDLER\n";
}
};
pcntl_signal(SIGALRM, $sighandler);
pcntl_signal(SIGTERM, $sighandler);
while (!$term)
{
do_work();
// Kick myself after 2 seconds
pcntl_alarm(2);
// Wait for alarm or termination
$signal = pcntl_sigwaitinfo(array(SIGTERM, SIGALRM), $info);
pcntl_signal_dispatch();
switch ($signal)
{
case SIGALRM: echo "ALRM SIGWI\n"; break;
case SIGTERM: echo "TERM SIGWI\n"; $term = TRUE; break;
}
}
// ...
但是看在上帝的份上,我无法弄清楚为什么永远不会调用 sighandler。我得到以下输出:
$ php sigsample.php
Doing some work.
ALRM SIGWI
Doing some work.
ALRM SIGWI
Doing some work.
TERM SIGWI
同时,如果我不设置这个处理程序,脚本会因为 unhandler 信号而死掉。
我错过了什么吗?为什么我的信号处理函数从未被调用?pcntl_sigwaitinfo() 会干扰吗?
还有其他方法可以同时实现超时和信号处理吗?