PHP:读取管道流时线程崩溃

PHP:读取管道流时线程崩溃,php,windows,multithreading,pthreads,proc-open,Php,Windows,Multithreading,Pthreads,Proc Open,我目前正在用PHP开发一个部署框架,遇到了一些关于线程和流的问题 我想启动一个进程,读取它的stdout和stderr(分别!),回显它,并在进程终止时返回流的完整内容 为了实现这一功能,我使用了两个线程,每个线程读取不同的流(stdout | stderr)。现在我遇到的问题是,当第二次调用fgets时,php正在崩溃。(错误代码0x5,错误偏移量0x000610e7) 经过大量的跟踪和错误,我发现当我向run函数添加一个虚拟数组时,崩溃并不总是发生,而且它的工作方式与预期的一样。 有人知道为

我目前正在用PHP开发一个部署框架,遇到了一些关于线程和流的问题

我想启动一个进程,读取它的stdout和stderr(分别!),回显它,并在进程终止时返回流的完整内容

为了实现这一功能,我使用了两个线程,每个线程读取不同的流(stdout | stderr)。现在我遇到的问题是,当第二次调用fgets时,php正在崩溃。(错误代码0x5,错误偏移量0x000610e7)

经过大量的跟踪和错误,我发现当我向
run
函数添加一个虚拟数组时,崩溃并不总是发生,而且它的工作方式与预期的一样。 有人知道为什么会这样吗

我使用的是Windows7、PHP5.4.22、MSVC9、pthreads 2.0.9

private static $pipeSpecsSilent = array(
   0 => array("pipe", "r"), // stdin
   1 => array("pipe", "w"), // stdout
   2 => array("pipe", "w")); // stderr

public function start()
{
    $this->procID = proc_open($this->executable, $this::$pipeSpecsSilent, $this->pipes);
    if (is_resource($this->procID))
    {
        $stdoutThread = new POutputThread($this->pipes[1]);
        $stderrThread = new POutputThread($this->pipes[2]);
        $stderrThread->start();
        $stdoutThread->start();

        $stdoutThread->join();
        $stderrThread->join();

        $stdout = trim($stdoutThread->getStreamValue());
        $stderr = trim($stderrThread->getStreamValue());

        $this->stop();
        return array('stdout' => $stdout, 'stderr' => $stderr);
    }
    return null;
}

/**
 * Closes all pipes and the process handle
 */
private function stop()
{
    for ($x = 0; $x < count($this->pipes); $x++)
    {
        fclose($this->pipes[$x]);
    }

    $this->resultValue = proc_close($this->procID);
}


class POutputThread extends Thread
{
    private $pipe;
    private $content;

    public function __construct($pipe)
    {
        $this->pipe = $pipe;
    }

    public function run()
    {
        $content = '';

        // this line is requires as we get a crash without it.
        // it seems like there is something odd happening?
        $stackDummy = array('', '');

        while (($line = fgets($this->pipe)))
        {
            PLog::i($line);
            $content .= $line;
        }
        $this->content = $content;
    }

    /**
     * Returns the value of the stream that was read
     *
     * @return string
     */
    public function getStreamValue()
    {
        return $this->content;
    }
}
private static$pipeSpecsSilent=array(
0=>数组(“管道”、“r”),//stdin
1=>数组(“管道”,“w”),//标准输出
2=>数组(“管道”,“w”);//标准错误
公共功能启动()
{
$this->procID=proc\u open($this->executable,$this::$pipeSpecsSilent,$this->pipes);
如果(是_资源($this->procID))
{
$stdoutThread=newpoutputhread($this->pipes[1]);
$stderrThread=newpoutputhread($this->pipes[2]);
$stderrThread->start();
$stdoutThread->start();
$stdoutThread->join();
$stderrThread->join();
$stdout=trim($stdoutThread->getStreamValue());
$stderr=trim($stderrThread->getStreamValue());
$this->stop();
返回数组('stdout'=>$stdout,'stderr'=>$stderr);
}
返回null;
}
/**
*关闭所有管道和进程句柄
*/
私有函数stop()
{
对于($x=0;$xpipes);$x++)
{
fclose($this->pipes[$x]);
}
$this->resultValue=proc\u close($this->procID);
}
类POutputThread扩展线程
{
私人管道;
私人内容;
公共功能建筑($pipe)
{
$this->pipe=$pipe;
}
公共功能运行()
{
$content='';
//这条线是必需的,因为没有它我们会撞车。
//好像有什么奇怪的事情发生了?
$stackDummy=数组(“”,”);
而(($line=fgets($this->pipe)))
{
PLog::i($行);
$content.=$line;
}
$this->content=$content;
}
/**
*返回读取的流的值
*
*@返回字符串
*/
公共函数getStreamValue()
{
返回$this->content;
}
}
我发现了问题:

虽然我在所有线程终止后关闭流,但似乎需要关闭从中读取的线程内部的流。 所以我替换了
$this->stop()使用
fclose($this->pipe)调用
运行
函数中,一切正常