父母孩子在分叉后没有发出信号

时间:2014-01-21 10:26:38

标签: php symfony-1.4 fork pcntl

我在使用symfony 1.4的PHP中遇到了一个奇怪的问题

我有一个启动多个工作人员的任务,有时我需要停止所有工作人员(例如,在部署之后)。

我使用start-stop-daemon启动任务,我想通过发送SIGINT信号来阻止它。

所以,这是我的代码:

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

我所做的非常简单:我分叉,创建N个子进程,在父对象中,我添加一个pcntl_signal来捕获SIGINT信号。 signalHanlder函数检索子pids列表并向它们发送刚收到的相同信号(所以SIGINT)。

问题是当我向父进程发送INT信号(通过kill)时,从不调用signalHandler函数。我不明白为什么!

奇怪的是,当我在cli中启动任务并使用Ctrl-C时,将调用signalHandler函数并停止所有子项。

那么,你明白为什么会这样吗?我做错了吗?

1 个答案:

答案 0 :(得分:0)

好的,忘记了,我在问了这个问题后才发现问题:

我刚刚更换了

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

通过

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

因为当然,这个过程正在等待其中一个孩子死亡。