Как мне использовать $status, возвращаемый pcntl waitpid()?


У меня есть договоренность между родителями и работниками. Родитель хранит рабочие PID в массиве, постоянно проверяя, что они все еще живы, с помощью следующего цикла:

// $workers is an array of PIDs
foreach ($workers as $workerID => $pid) {
    // Check if this worker still exists as a process
    pcntl_waitpid($pid, $status, WNOHANG|WUNTRACED);

    // If the worker exited normally, stop tracking it
    if (pcntl_wifexited($status)) {
        $logger->info("Worker $workerID exited normally");
        array_splice($workers, $workerID, 1); 
    }

    // If it has a session ID, then it's still living
    if (posix_getsid($pid))⋅
        $living[] = $pid;
}

// $dead is the difference between workers we've started
// and those that are still running
$dead = array_diff($workers, $living);

Проблема в том, что pcntl_waitpid() всегда устанавливает $status в 0, поэтому при первом запуске этого цикла родитель думает, что все его дочерние элементы вышли нормально, даже если они все еще работают. Я неправильно использую pcntl_waitpid() или ожидаю, что он сделает что-то, чего он не делает?

Author: hakre, 2011-01-03

2 answers

Просто, ребенок не вышел и не остановился. Вы добавили WNOHANG флаг, поэтому он всегда будет возвращаться немедленно (он говорит функции не ждать события). Что вам следует сделать, так это проверить возвращаемое значение pcntl_waitpid, чтобы узнать, было ли возвращено что-либо ценное (при условии, что вы хотите запустить содержимое цикла только в случае изменения статуса):

foreach ($workers as $workerID => $pid) {
    // Check if this worker still exists as a process
    if (pcntl_waitpid($pid, $status, WNOHANG|WUNTRACED)) {
        // If the worker exited normally, stop tracking it
        if (pcntl_wifexited($status)) {
            $logger->info("Worker $workerID exited normally");
            array_splice($workers, $workerID, 1); 
        }
        // If it has a session ID, then it's still living
        if (posix_getsid($pid))⋅
            $living[] = $pid;
    }
}    
 3
Author: ircmaxell, 2011-01-03 16:27:01

Вы действительно "неправильно используете pcntl_waitpid()" (Обратите внимание на кавычки)

Так как вы используете WNOHANG, только если pcntl_waitpid() возвращает PID ребенка, вы можете оценить, что в $status.

Смотрите возвращаемые значения для pcntl_waitpid().

 2
Author: Linus Kleen, 2011-01-03 16:27:05