根据PHPdocsfor等,
等待函数将当前进程的执行挂起,直到子进程退出,或直到信号被传递,其操作是终止当前进程或调用信号处理函数。
但是,当我运行以下代码并使用kill -s SIGTERM [pid]向父进程发送SIGTERM时,只有在子进程退出后才调用信号处理程序(也就是说,我必须等待睡眠结束。pcntl_wait()不应该被SIGTERM打断吗?
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
SIGTERMPHP版本=> 5.3.3
发布于 2012-04-24 01:03:36
您对pcntl_signal的调用指定应该重新启动该调用。检查文档,默认情况下restart_syscalls是true。因此,在孩子终止之前,您对pcntl_signal的电话不会返回。
你没有打电话给同花顺。所以PHP可以将echo的输出保存在缓冲区中。
所以你所看到的行为正是你所要求的行为。系统调用被重新启动,输出被缓冲。
发布于 2020-01-22 15:48:55
pcntl_wait调用不能被信号中断,除非restart_syscalls=false或子节点死亡。
来自wait syscall的文档(这是pcntl_wait所调用的):
..。它们会阻塞,直到子更改状态或信号处理程序中断调用为止(假设系统调用不会使用sigaction(2)的SA_RESTART标志自动重新启动SA_RESTART)。
最后一部分是非常重要的。只有当系统调用没有自动重新启动(restart_syscalls=false)时,调用才会中断。
有趣的是,当一个进程接收到信号时,并不是所有syscall的行为都是相同的。例如,sleep syscall将等待秒数或等待任何信号才能继续。即使您通过了sleep,也不会在它被插入的地方重新启动它。来自sleep手册:
have ()会导致调用线程处于休眠状态,直到秒内指定的实时秒数过去,或者直到信号到达,而信号不会被忽略.。
除非您通过restart_syscalls=false**.**,否则不能中断TL;DR;pcntl_wait
https://stackoverflow.com/questions/10290366
复制相似问题