Если вы захватываете сигнал, вам придется когда-нибудь проверить его. Если вы зависаете в блокирующем waitpid()
, используйте declare(ticks=1);
в верхней части ваших сценариев или используйте WNOHANG
в цикле (возможно, sleep
ing) и вызывайте 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
только после разветвления.