I have a parent/worker arrangement going on. The parent keeps the worker PIDs in an array, constantly checking that they are still alive with the following loop:
// $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);
The problem is that pcntl_waitpid()
is always setting 开发者_JAVA百科$status
to 0, so the very first time this loop is run, the parent thinks that all of its children have exited normally, even though they are still running. Am I using pcntl_waitpid()
incorrectly, or expecting it to do something that it doesn't?
Simple, the child has not exited or stopped. You added the WNOHANG
flag, so it will always return immediately (It tells the function not to wait for an event). What you should do is check the return value of pcntl_waitpid
to see if anything of value was returned (assuming that you only want to run the contents of the loop if there's a status change):
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;
}
}
You're indeed "using pcntl_waitpid()
wrong" (Note the quotes)
Since you're using WNOHANG
, only if pcntl_waitpid()
returns the child's PID, you may evaluate what's in $status
.
See return values for pcntl_waitpid()
.
精彩评论