Skip to content

Commit e7bdc8a

Browse files
committed
Issue #20 Tweak handling of input streams
1 parent d3bc082 commit e7bdc8a

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

src/Command.php

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,7 @@ public function execute()
398398
stream_set_blocking($pipes[2], false);
399399
if ($hasInput) {
400400
$writtenBytes = 0;
401+
$isInputOpen = true;
401402
stream_set_blocking($pipes[0], false);
402403
if ($isInputStream) {
403404
stream_set_blocking($this->_stdIn, false);
@@ -408,10 +409,10 @@ public function execute()
408409
// a loop if the process is still running. We also need to
409410
// ensure that all the pipes are written/read alternately
410411
// until there's nothing left to write/read.
411-
$running = true;
412-
while ($running) {
412+
$isRunning = true;
413+
while ($isRunning) {
413414
$status = proc_get_status($process);
414-
$running = $status['running'];
415+
$isRunning = $status['running'];
415416

416417
// We first write to stdIn if we have an input. For big
417418
// inputs it will only write until the input buffer of
@@ -421,10 +422,11 @@ public function execute()
421422
//
422423
// After everything is written it's safe to close the
423424
// input pipe.
424-
if ($hasInput && $running) {
425+
if ($isRunning && $hasInput && $isInputOpen) {
425426
if ($isInputStream) {
426427
$written = stream_copy_to_stream($this->_stdIn, $pipes[0], 16 * 1024, $writtenBytes);
427428
if ($written === false || $written === 0) {
429+
$isInputOpen = false;
428430
fclose($pipes[0]);
429431
} else {
430432
$writtenBytes += $written;
@@ -433,14 +435,15 @@ public function execute()
433435
if ($writtenBytes < strlen($this->_stdIn)) {
434436
$writtenBytes += fwrite($pipes[0], substr($this->_stdIn, $writtenBytes));
435437
} else {
438+
$isInputOpen = false;
436439
fclose($pipes[0]);
437440
}
438441
}
439442
}
440443

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

457-
if (!$running) {
460+
if (!$isRunning) {
458461
$this->_exitCode = $status['exitcode'];
459462
fclose($pipes[1]);
460463
fclose($pipes[2]);

tests/CommandTest.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,4 +256,28 @@ public function testCanRunCommandWithBigInputAndOutput()
256256
$this->assertTrue($command->getExecuted());
257257
$this->assertEquals(strlen($string), strlen($command->getOutput()));
258258
}
259+
public function testCanRunLongRunningCommandWithBigInputAndOutput()
260+
{
261+
$string = str_repeat('01234567890abcdef', 16 * 1024); // 16 * 16 * 1024 = 256KB
262+
$command = new Command('/bin/cat; echo "start" ; sleep 2 ; echo "done"');
263+
$command->setStdIn($string);
264+
$this->assertTrue($command->execute());
265+
$this->assertTrue($command->getExecuted());
266+
$expected = $string . "start\ndone";
267+
$this->assertEquals(strlen($expected), strlen($command->getOutput()));
268+
}
269+
public function testCanRunLongRunningCommandWithStandardInputStream()
270+
{
271+
$string = str_repeat('01234567890abcdef', 16 * 1024); // 16 * 16 * 1024 = 256KB
272+
$tmpfile = tmpfile();
273+
fwrite($tmpfile, $string);
274+
fseek($tmpfile, 0);
275+
$command = new Command('/bin/cat; echo "start" ; sleep 2 ; echo "done"');
276+
$command->setStdIn($tmpfile);
277+
$this->assertTrue($command->execute());
278+
$this->assertTrue($command->getExecuted());
279+
$expected = $string . "start\ndone";
280+
$this->assertEquals(strlen($expected), strlen($command->getOutput()));
281+
fclose($tmpfile);
282+
}
259283
}

0 commit comments

Comments
 (0)