如果您要捕获信号,则必须在某个时候检查它们。如果你挂在一个阻塞的waitpid(),在你的脚本顶部使用declare(ticks=1);,或者在循环中使用WNOHANG(可能是sleeping),然后调用pcntl_signal_dispatch()。
这不起作用:
<?php
pcntl_signal(SIGTERM, 'kill_handler');
function kill_handler($no){
global $pid;
posix_kill($pid,SIGTERM);
echo 'Done killing '.$pid.PHP_EOL;
exit;
}
$pid = pcntl_fork();
if ($pid) {
echo 'Forked, parent is'.posix_getpid().PHP_EOL;
pcntl_waitpid($pid,$status);
} else {
echo 'child '.posix_getpid().PHP_EOL;
$i = 0;
while($i++ < 30){
echo date('H:i:s').PHP_EOL;
sleep(1);
}
echo 'done'.PHP_EOL;
}
?>
这对父母和孩子都有效:
<?php
declare(ticks=1);
//rest of previous code
?>
如果没有滴答声,这会让父级在 SIGTERM 上死掉,但由于子级没有信号调度,子级会继续:
<?php
pcntl_signal(SIGTERM, 'kill_handler');
function kill_handler($no){
global $pid;
posix_kill($pid,SIGTERM);
echo 'Done killing '.$pid.PHP_EOL;
exit;
}
$pid = pcntl_fork();
if ($pid) {
echo 'Forked, parent is'.posix_getpid().PHP_EOL;
while(0==pcntl_waitpid($pid,$status,WNOHANG)){
echo "nothing yet".PHP_EOL;
pcntl_signal_dispatch();
sleep(1);
}
} else {
echo 'child '.posix_getpid().PHP_EOL;
$i = 0;
while($i++ < 30){
echo date('H:i:s').PHP_EOL;
sleep(1);
}
echo 'done'.PHP_EOL;
}
?>
因此,要么您必须在孩子本身中调用pcntl_signal_dispatch(),要么您必须在分叉后才调用pcntl_signal。