If you are capturing a signal, you'll have to check them sometime. If you are hanging in a blocking waitpid()
, use declare(ticks=1);
at the top of your scripts, or use a WNOHANG
in a loop (possiblye sleep
ing), and call pcntl_signal_dispatch()
.
This does not work:
<?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;
}
?>
This would work for both parent & child:
<?php
declare(ticks=1);
//rest of previous code
?>
Without ticks, this would let the parent die on a SIGTERM, but because there is no signal dispatch in the child the child continues:
<?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;
}
?>
So either you'll have to call pcntl_signal_dispatch()
in the child itself, or you'll have to call pcntl_signal
only after forking.