私は現在、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;
}
}