Parent child does not catch signal after forking

681 Views Asked by At

I'm having a weird problem in PHP with symfony 1.4

I have a task that launches multiple workers, and, sometimes, I need to stop all the workers (for example, after a deployment).

I launch the task using start-stop-daemon, and I want to stop it by sending the signal SIGINT to it.

So, here is my code:

protected function execute($arguments = array(), $options = array())
{
    $pid_arr = array();
    $thread = $this->forkChildren($arguments, $options, $options['nb_children']);

    if ($this->iAmParent())
    {
        declare(ticks = 1);
        pcntl_signal(SIGINT, array($this, 'signalHandler'));
        // Retrieve list of children PIDs
        $pid_arr = $this->getChildrenPids();
        // While there are still children processes
        while(count($pid_arr) > 0)
        {
            $myId = pcntl_waitpid(-1, $status);
            foreach($pid_arr as $key => $pid)
            {
                // If the stopped process is indeed a children of the parent process
                if ($myId == $pid)
                {
                    $this->removeChildrenPid($key);
                    // Recreate a child
                    $this->createNewChildren($arguments, $options, 1, $pid_arr);
                }
            }
            usleep(1000000);
            $pid_arr = $this->getChildrenPids();
        }
    }
    else
        $thread->run();
}

public function signalHandler($signal)
{
    echo "HANDLED SIGNAL $signal\n";
    foreach ($this->getChildrenPids() as $childrenPid)
    {
        echo "KILLING $childrenPid\n";
        posix_kill($childrenPid, $signal);
    }
    exit();
}

What I do is quite straightforward: I fork, create N children processes, and in the parent, I add a pcntl_signal to catch the SIGINT signal. The signalHanlder function retrieves the list of children pids and sends them the same signal it just received (so SIGINT).

The problem is that the signalHandler function is never called when I send a INT signal (via kill) to the parent process. And I don't understand why!

The weird thing is that when I launch my task in cli and uses Ctrl-C, the signalHandler function is called and all the children are stopped.

So, do you understand why is this happening? Am I doing something wrong?

1

There are 1 best solutions below

0
On

OK, forget about it, I found the problem just after asking the question:

I just replaced

$myId = pcntl_waitpid(-1, $status);

by

$myId = pcntl_waitpid(-1, $status, WNOHANG);

because of course, the process was hung waiting for one of the children to die.