1

私は現在、PHP で展開フレームワークを開発しており、スレッドとストリームに関していくつかの問題があります。

プロセスを開始し、その stdout と stderr を (別々に!) 読み取り、それをエコーし​​、プロセスが終了したときにストリームの完全な内容を返したいと考えています。

その機能を実現するために、私は 2 つのスレッドを使用しており、それぞれが異なるストリーム (stdout|stderr) を読み取っています。これで私が得た問題は、fgetsが2回目に呼び出されたときにphpがクラッシュすることです。(エラー コード 0x5、エラー オフセット 0x000610e7)。

多くの試行錯誤の後、run関数にダミー配列を追加すると、クラッシュが常に発生するとは限らず、期待どおりに機能することがわかりました。なぜこれが起こっているのか誰にも分かりますか?

Windows 7、PHP 5.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;
    }
}
4

1 に答える 1

1

私は問題を見つけました:

すべてのスレッドが終了した後にストリームを閉じていますが、ストリームから読み取っていたスレッド内のストリームを閉じる必要があるようです。$this->stop();そのため、呼び出しを関数fclose($this->pipe);内のaに置き換えた runところ、すべて正常に機能しました。

于 2015-01-14T12:58:45.737 に答える