避免分叉后出现空闲页面


Avoid idle page after fork

经过大量的努力,我终于让我的php-Zond应用程序用多线程运行。为此,我在CGI模式下配置了Apache,以便使用php-pcntl_*函数。我有这个问题这是我的叉子

    function fork() {
    $pid = pcntl_fork();
    if ($pid == -1)
        throw new Exception('fork error on Task object');
    elseif ($pid) {
        # we are in parent class
        $this->pid = $pid;
        # echo "< in parent with pid {$his->pid}'n";
    } else {
        # we are in child
        $sid = posix_setsid();
        if ($sid < 0) {
            exit;
        }
        $this->run();
    }
}

每次我调用这个函数时,都会创建一个进程,它运行得很完美,但我失去了对浏览器上网页的控制(我无法再浏览我的网站)。它似乎加载页面很长时间,直到它给我一个错误。我需要关闭浏览器(只需一个新的选项卡,我无法重新连接),然后重新连接到服务器。可能是最后一个创建的进程正在侦听我的http端口吗?我该如何解决这个问题?感谢

对我来说,这听起来像是一个会话锁定问题——无论何时调用session_start(),PHP都会对磁盘上的会话文件进行独占锁定,这样两个PHP页面就不会向同一会话写入冲突信息。如果在锁定到位时调用session_start(),它将"挂起",直到锁定会话的进程完成(或调用session_write_close()session_destroy())。

我的猜测是,在你"分叉"你的PHP进程之前,你正在打开一个会话(或者可能使用其他一些独占锁),而这个锁没有被正确释放,因为PHP不是为在多线程(或者更确切地说,多进程)环境中使用而设计的。

与其试图让真正的分叉在PHP下工作,不如用systemexec生成一个全新的PHP脚本,并使用ZeroMQ等消息传递框架将序列化数据传递给它。这样,您不仅可以基于父级设置子级的初始条件,而且实际上还可以从子级传递信息。

但是,不要忘记,以这种方式创建的子进程将在"命令行SAPI"下运行,它可能受不同的php.ini的约束,并且不会定义通常认为理所当然的东西,如$_SERVER['DOCUMENT_ROOT']