pcntl_signal_dispatch

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

pcntl_signal_dispatch调用待处理信号的信号处理程序

描述

pcntl_signal_dispatch(): bool

函数 pcntl_signal_dispatch() 会调用由 pcntl_signal() 安装的信号处理程序,以处理每个待处理的信号。

参数

此函数没有参数。

返回值

成功时返回 true,失败时返回 false

范例

范例 #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";

?>

上面的例子将输出类似于以下内容

Installing signal handler...
Generating signal SIGHUP to self...
Dispatching...
signal handler called
Done

参见

添加说明

用户贡献说明 4 个说明

webmaster at ajeux dot com
15 年前
如果您正在以 CLI 和“守护进程”模式(即在循环中)运行 PHP,则必须在每个循环中调用此函数以检查是否有新的信号正在等待分派。
me at subsonic dot cz
10 年前
请注意,从由先前 pcntl_signal_dispatch() 调用的信号处理程序内部调用 pcntl_signal_dispatch() 不会触发任何新的待处理信号的处理程序。这意味着如果您编写了一个 CLI 守护进程,该守护进程响应信号而派生出子进程,那么这些子进程将无法响应信号。这让我头疼了好一阵子,因为当这种情况发生时,pcntl_signal_dispatch() 不会引发任何错误。一种解决方法是在信号处理程序中设置一个标志,并在父进程的主循环中的其他地方对其进行响应(通过派生所需的子进程)。
stefanis
10 年前
如“me at subsonic dot net” 所述,从由先前 pcntl_signal_dispatch() 调用的信号处理程序内部调用 pcntl_signal_dispatch() 不会触发任何新的待处理信号的处理程序。即使您 pcntl_exec() 一个新的 PHP 处理器来执行一个完全不同的脚本,似乎也是如此。

解决方案似乎是在 ticks_handler() 内部显式调用 pcntl_signal_dispatch() 。并将 sig_handler(int) 作为函数推送到队列中。在 ticks_handler 中调用 dispatch 之后,立即弹出队列,执行您原本在 signal_handler 中执行的操作,直到队列为空。
stefanis
10 年前
嗯,我之前说错了。在信号处理程序之外处理信号是不够的。它们必须在滴答处理程序(显式或隐式)之外进行处理。所以...

注册一个调用 pcntl_signal_dispatch() 的滴答处理程序;
在信号处理程序中,将您的信号入队;
在脚本的主循环中,处理您的信号;

<?php
declare(ticks=1);
global
$sig_queue;
global
$use_queue;
$sig_queue = array();
$use_queue = true; // 设置为 false 以使用旧方法

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("派生了 $pid\n");
break;

default:
print(
"未处理的信号: $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);
}
?>
To Top