Skip to content

Commit

Permalink
Issue #20 Tweak handling of input streams
Browse files Browse the repository at this point in the history
  • Loading branch information
mikehaertl committed Aug 16, 2019
1 parent d3bc082 commit e7bdc8a
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 6 deletions.
15 changes: 9 additions & 6 deletions src/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,7 @@ public function execute()
stream_set_blocking($pipes[2], false);
if ($hasInput) {
$writtenBytes = 0;
$isInputOpen = true;
stream_set_blocking($pipes[0], false);
if ($isInputStream) {
stream_set_blocking($this->_stdIn, false);
Expand All @@ -408,10 +409,10 @@ public function execute()
// a loop if the process is still running. We also need to
// ensure that all the pipes are written/read alternately
// until there's nothing left to write/read.
$running = true;
while ($running) {
$isRunning = true;
while ($isRunning) {
$status = proc_get_status($process);
$running = $status['running'];
$isRunning = $status['running'];

// We first write to stdIn if we have an input. For big
// inputs it will only write until the input buffer of
Expand All @@ -421,10 +422,11 @@ public function execute()
//
// After everything is written it's safe to close the
// input pipe.
if ($hasInput && $running) {
if ($isRunning && $hasInput && $isInputOpen) {
if ($isInputStream) {
$written = stream_copy_to_stream($this->_stdIn, $pipes[0], 16 * 1024, $writtenBytes);
if ($written === false || $written === 0) {
$isInputOpen = false;
fclose($pipes[0]);
} else {
$writtenBytes += $written;
Expand All @@ -433,14 +435,15 @@ public function execute()
if ($writtenBytes < strlen($this->_stdIn)) {
$writtenBytes += fwrite($pipes[0], substr($this->_stdIn, $writtenBytes));
} else {
$isInputOpen = false;
fclose($pipes[0]);
}
}
}

// Read out the output buffers because if they are full
// the command may block execution. We do this even if
// $running is `false`, because there could be output
// $isRunning is `false`, because there could be output
// left in the buffers.
//
// The latter is only an assumption and needs to be
Expand All @@ -454,7 +457,7 @@ public function execute()
$this->_stdErr .= $err;
}

if (!$running) {
if (!$isRunning) {
$this->_exitCode = $status['exitcode'];
fclose($pipes[1]);
fclose($pipes[2]);
Expand Down
24 changes: 24 additions & 0 deletions tests/CommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -256,4 +256,28 @@ public function testCanRunCommandWithBigInputAndOutput()
$this->assertTrue($command->getExecuted());
$this->assertEquals(strlen($string), strlen($command->getOutput()));
}
public function testCanRunLongRunningCommandWithBigInputAndOutput()
{
$string = str_repeat('01234567890abcdef', 16 * 1024); // 16 * 16 * 1024 = 256KB
$command = new Command('/bin/cat; echo "start" ; sleep 2 ; echo "done"');
$command->setStdIn($string);
$this->assertTrue($command->execute());
$this->assertTrue($command->getExecuted());
$expected = $string . "start\ndone";
$this->assertEquals(strlen($expected), strlen($command->getOutput()));
}
public function testCanRunLongRunningCommandWithStandardInputStream()
{
$string = str_repeat('01234567890abcdef', 16 * 1024); // 16 * 16 * 1024 = 256KB
$tmpfile = tmpfile();
fwrite($tmpfile, $string);
fseek($tmpfile, 0);
$command = new Command('/bin/cat; echo "start" ; sleep 2 ; echo "done"');
$command->setStdIn($tmpfile);
$this->assertTrue($command->execute());
$this->assertTrue($command->getExecuted());
$expected = $string . "start\ndone";
$this->assertEquals(strlen($expected), strlen($command->getOutput()));
fclose($tmpfile);
}
}

0 comments on commit e7bdc8a

Please sign in to comment.