Как использовать $ status, возвращаемый pcntl_waitpid ()? - PullRequest
2 голосов
/ 03 января 2011

У меня есть договоренность с родителем / работником.Родитель хранит рабочие 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() или ожидаю, что он сделает то, чего не делает?

Ответы [ 2 ]

3 голосов
/ 03 января 2011

Простой, ребенок не вышел или не остановился.Вы добавили флаг 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;
    }
}    
2 голосов
/ 03 января 2011

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

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

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

...