Question

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 $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?

Was it helpful?

Solution

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;
    }
}    

OTHER TIPS

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().

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top