Skip to content

Commit

Permalink
fix reading zero after process exits
Browse files Browse the repository at this point in the history
  • Loading branch information
halaei committed Aug 28, 2021
1 parent 7213982 commit 15cd668
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 16 deletions.
39 changes: 23 additions & 16 deletions src/Process/Process.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,22 +111,9 @@ public function mustRun()
*/
public function run()
{
$descriptors = [
['pipe', 'r'],
['pipe', 'w'],
['pipe', 'w'],
];
$this->startedAt = microtime(true);
// 'exec' is used to make sure the process is the immediate child, otherwise it will be the child of a child sh process.
$this->process = proc_open('exec '.$this->getCommandLine(), $descriptors, $this->pipes, $this->cwd, $this->env);
if (! is_resource($this->process)) {
if (! $this->start()) {
return null;
}
$this->result = new ProcessResult();
foreach ($this->pipes as $pipe) {
stream_set_blocking($pipe, false);
}

$inputClosed = false;
for ($this->status = proc_get_status($this->process); $this->status['running'] && ! $this->result->timedOut; $this->status = proc_get_status($this->process)) {
$ready = $this->wait($inputClosed);
Expand Down Expand Up @@ -170,10 +157,10 @@ public function run()
try {
stream_set_blocking($this->pipes[1], true);
stream_set_blocking($this->pipes[2], true);
while ($read = fread($this->pipes[1], 16384)) {
while (($read = fread($this->pipes[1], 16384)) !== false && strlen($read)) {
$this->result->stdOut .= $read;
}
while ($read = fread($this->pipes[2], 16384)) {
while (($read = fread($this->pipes[2], 16384)) !== false && strlen($read)) {
$this->result->stdErr .= $read;
}
} catch (\Exception $e) {
Expand All @@ -190,6 +177,26 @@ public function run()
return $this->result;
}

protected function start()
{
$descriptors = [
['pipe', 'r'],
['pipe', 'w'],
['pipe', 'w'],
];
$this->startedAt = microtime(true);
// 'exec' is used to make sure the process is the immediate child, otherwise it will be the child of a child sh process.
$this->process = proc_open('exec '.$this->getCommandLine(), $descriptors, $this->pipes, $this->cwd, $this->env);
if (! is_resource($this->process)) {
return false;
}
$this->result = new ProcessResult();
foreach ($this->pipes as $pipe) {
stream_set_blocking($pipe, false);
}
return true;
}

/**
* Gets the command line to be executed.
*
Expand Down
13 changes: 13 additions & 0 deletions tests/ProcessTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,17 @@ public function test_timeout()
$this->assertTrue($p->run()->timedOut);
$this->assertLessThan(5, microtime(true) - $t);
}

public function test_reading_zero_after_process_ends()
{
$p = new class(['echo', '-n', '0']) extends Process {
protected function start()
{
$started = parent::start();
sleep(1);
return $started;
}
};
$this->assertSame('0', $p->run()->stdOut);
}
}

0 comments on commit 15cd668

Please sign in to comment.