PHP - дочерний процесс, блокирующий SIGTERM для родителя - PullRequest
2 голосов
/ 18 июля 2010

У меня проблемы с уничтожением родительского процесса, у которого есть 1 дочерний элемент - родитель ожидает выхода дочернего элемента и только после вызова этого обработчика уничтожения. Когда обработчик уничтожения не установлен (pcntl_signal (SIGTERM, "kill_handler")), сценарий немедленно завершается.

Мне нужно, чтобы после отправки команды kill для завершения родительского процесса сигнал был немедленно получен функцией обработки kill. Затем эта функция убьет дочерний процесс.

Есть идеи?

1 Ответ

1 голос
/ 28 июля 2010

Если вы захватываете сигнал, вам придется когда-нибудь проверить его. Если вы зависаете в блокирующем 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 только после разветвления.

...