我正在编写一个守护进程,它周期性地做一些工作,并在再次重复之前休眠一段时间。但它在休眠时仍必须对外部冲击(即终止请求)作出响应。
我设法用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同时,如果我不设置这个处理程序,脚本就会因为未处理程序信号而终止。
我漏掉了什么吗?为什么我的信号处理函数从未被调用过?是pcntl_sigwaitinfo()干扰吗?
还有没有其他方法可以同时实现超时和信号处理?
发布于 2012-10-11 11:08:05
这并不完全出乎意料。
您已经请求传递到一个信号处理程序(pcntl_signal(...)),但随后又要求在不调用任何处理程序(pcntl_sigwaitinfo(...))的情况下接受该信号。你的操作系统可以决定在这种情况下会发生什么,而你的操作系统(和我的操作系统一样)选择让pcntl_sigwaitinfo()获胜。
背景
一个进程可以接收(“遭受?”)以两种不同的方式发送信号:
该信号引发一些异步操作,通常终止进程或调用用户定义的处理程序。pcntl_signal就注册了这样一个处理程序。
C程序员熟悉的基础调用是signal和sigaction.
特殊的系统函数注意到一个信号是挂起的,并将其从挂起列表中删除,将有关该信号的信息返回给进程。pcntl_sigwaitinfo就是这样一个函数。
底层调用是sigwait、sigwaitinfo和sigtimedwait.
交付和验收这两种方式是different和不能一起使用的。例如,AIX简单地禁止"[c]oncurrent use of and "。
(与以上相关的是信号掩码的概念,它可以“阻塞”信号,有效地迫使它们保持挂起状态,直到被接受或直到“解除阻塞”和交付。)
https://stackoverflow.com/questions/12826297
复制相似问题