根据pcntl_wait的PHP文档,
wait函数暂停当前进程的执行,直到子进程退出,或者直到发出信号,其动作是终止当前进程或调用信号处理函数。
但是,当我运行以下代码并使用kill -s SIGTERM [pid]
将SIGTERM发送到父进程时,信号处理程序仅在子进程后被称为(即我必须等待睡眠完成.SIGTERM不应该pcntl_wait()
中断吗?
fork_test.php:
<?php
declare(ticks = 1);
function sig_handler($signo) {
switch ($signo) {
case SIGTERM:
echo 'SIGTERM' . PHP_EOL;
break;
default:
}
}
pcntl_signal(SIGTERM, 'sig_handler');
$pid = pcntl_fork();
if ($pid == -1) {
die('could not fork');
}
else if ($pid) {
echo 'parent' . PHP_EOL;
pcntl_wait($status);
}
else {
echo 'child' . PHP_EOL;
sleep(30);
}
?>
输出(SIGTERM仅在等待30秒后出现):
$ php fork_test.php
child
parent
SIGTERM
PHP Version =&gt; 5.3.3
答案 0 :(得分:3)
您对pcntl_signal
的呼叫指定应重新启动呼叫。默认情况下,请检查docs,restart_syscalls
为true
。因此,在孩子被终止之前,您对pcntl_signal
的呼叫不会返回。
您没有致电flush。因此,PHP可以将echo
的输出保存在缓冲区中。
因此,您所看到的行为正是您要求的行为。重新启动系统调用并缓冲输出。
答案 1 :(得分:0)
bool a; a = 25;
的呼叫不能被信号打断,除非pcntl_wait
或孩子死亡。
摘自restart_syscalls=false
syscall(wait
调用)的文档:
...它们阻塞,直到有一个孩子变了 状态或信号处理程序中断了调用(假设该系统 使用的SA_RESTART标志不会自动重新启动呼叫 sigaction(2))。
最后一部分非常重要。仅当系统调用没有自动重新启动(pcntl_wait
)时,呼叫才会中断。
restart_syscalls=false
syscall将等待秒数或等待任何信号后再继续。即使您通过sleep
,sleep
也不会在中断的地方重新启动。从restart_syscalls=true
手册中:
sleep()使调用线程进入睡眠状态,直到 以秒为单位指定的实时秒已过去或直到信号 到达,将被忽略。
TL; DR;除非您通过sleep
,否则pcntl_wait不会被中断。