Как мне использовать $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()
или ожидаю, что он сделает что-то, чего он не делает?
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;
}
}
Вы действительно "неправильно используете pcntl_waitpid()
" (Обратите внимание на кавычки)
Так как вы используете WNOHANG
, только если pcntl_waitpid()
возвращает PID ребенка, вы можете оценить, что в $status
.
Смотрите возвращаемые значения для pcntl_waitpid()
.