©
This document uses PHP Chinese website manual Release
(PHP 5 >= 5.3.0)
pcntl_signal_dispatch — 调用等待信号的处理器
函数 pcntl_signal_dispatch() 调用每个等待信号通过 pcntl_signal() 安装的处理器。
成功时返回 TRUE
, 或者在失败时返回 FALSE
。
Example #1 pcntl_signal_dispatch() 示例
<?php
echo "安装信号处理器...\n" ;
pcntl_signal ( SIGHUP , function( $signo ) {
echo "信号处理器被调用\n" ;
});
echo "为自己生成SIGHUP信号...\n" ;
posix_kill ( posix_getpid (), SIGHUP );
echo "分发...\n" ;
pcntl_signal_dispatch ();
echo "完成\n" ;
?>
以上例程的输出类似于:
安装信号处理器... 为自己生成SIGHUP信号... 分发... 信号处理器被调用 完成
[#1] stefanis [2014-05-13 18:45:47]
Well I misspoke before. It is not enough to process signals outside of the signal handler. They must be processed outside of the tick handler (explicit or implied). So...
Register a tick handler that calls pcntl_signal_dispatch();
In the signal handler, enqueue your signal;
In the main loop of your script, process your signals;
<?php
declare(ticks=1);
global $sig_queue;
global $use_queue;
$sig_queue = array();
$use_queue = true; // set to false to do it the old way
function tick_handler()
{
pcntl_signal_dispatch();
}
function sig_handler($sig)
{
global $sig_queue;
global $use_queue;
if(isset($use_queue) && $use_queue)
{
$sig_queue[] = $sig;
}
else
{
sig_helper($sig);
}
}
function sig_helper($sig)
{
switch($sig)
{
case SIGHUP:
$pid = pcntl_fork();
if($pid) print("forked $pid\n");
break;
default:
print("unhandled sig: $sig\n");
}
}
pcntl_signal(SIGHUP, "sig_handler");
while(true)
{
if($use_queue) foreach($sig_queue as $idx=>$sig)
{
sig_helper($sig);
unset($sig_queue[$idx]);
}
sleep(1);
}
?>
[#2] stefanis [2014-05-13 00:40:22]
As noted by "me at subsonic dot net" calling pcntl_signal_dispatch() from within a signal handler invoked by a previous pcntl_signal_dispatch() will not trigger handlers for any new pending signals. This seems to be true even if you pcntl_exec() a new PHP processor to execute an entirely different script.
The solution seems to be to explicitly call pcntl_signal_dispatch()inside a ticks_handler() . And use sig_handler(int) as a push function to a queue. Immediately following the call to dispatch in the ticks_handler, pop your queue doing what you would have done in the signal_handler until the queue is empty.
[#3] me at subsonic dot cz [2014-01-27 17:33:39]
Note that calling pcntl_signal_dispatch() from within a signal handler invoked by a previous pcntl_signal_dispatch() will not trigger handlers for any new pending signals. This means that if you write a CLI daemon which forks off child processes in response to a signal, then those child processes won't be able to respond to signals. This gave me a headache for a while as pcntl_signal_dispatch() doesn't raise any errors when this occurs. One solution is to set a flag within the signal handler and react upon it (by forking off the needed child processes) elsewhere in the parent process's main loop.
[#4] webmaster at ajeux dot com [2009-08-10 10:50:20]
If you are running PHP as CLI and as a "daemon" (i.e. in a loop), this function must be called in each loop to check if new signals are waiting dispatching.