Skip to content

Commit 57ba6f1

Browse files
committed
Issue #20 Add stream_set_blocking() calls for proc_open()
1 parent 9754f7d commit 57ba6f1

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

README.md

+5
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,11 @@ $command->setStdIn('string');
9393
PHP working dir.
9494
* `$procEnv`: An array with environment variables to pass to `proc_open()`. Default is `null` for none.
9595
* `$procOptions`: An array of `other_options` for `proc_open()`. Default is `null` for none.
96+
* `$nonBlockingMode`: Whether to set the stdout/stderr streams to non-blocking
97+
mode when `proc_open()` is used. This can fix issues with long running
98+
commands that hang indefinitely but can cause problems on Windows systems.
99+
The default is `null` in which case non-blocking mode is only enabled on
100+
non-Windows systems.
96101
* `$locale`: The locale to (temporarily) set with `setlocale()` before running the command.
97102
This can be set to e.g. `en_US.UTF-8` if you have issues with UTF-8 encoded arguments.
98103

src/Command.php

+20-2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ class Command
5353
*/
5454
public $procOptions;
5555

56+
/**
57+
* @var bool|null whether to set the stdout/stderr streams to non-blocking mode
58+
* when `proc_open()` is used. This can fix issues with long running
59+
* commands that hang indefinitely but can cause problems on Windows
60+
* systems. The default is `null` in which case non-blocking mode is only
61+
* enabled on non-Windows systems.
62+
*/
63+
public $nonBlockingMode;
64+
5665
/**
5766
* @var null|string the locale to temporarily set before calling `escapeshellargs()`. Default is `null` for none.
5867
*/
@@ -345,6 +354,13 @@ public function execute()
345354
$process = proc_open($command, $descriptors, $pipes, $this->procCwd, $this->procEnv, $this->procOptions);
346355

347356
if (is_resource($process)) {
357+
// Issue #20 Set non-blocking mode to fix hanging processes
358+
$nonBlocking = $this->nonBlockingMode === null ?
359+
!$this->getIsWindows() : $this->nonBlockingMode;
360+
if ($nonBlocking) {
361+
stream_set_blocking($pipes[1], false);
362+
stream_set_blocking($pipes[2], false);
363+
}
348364

349365
if ($this->_stdIn!==null) {
350366
if (is_resource($this->_stdIn) &&
@@ -362,8 +378,10 @@ public function execute()
362378

363379
$this->_exitCode = proc_close($process);
364380

365-
if ($this->_exitCode!==0) {
366-
$this->_error = $this->_stdErr ? $this->_stdErr : "Failed without error message: $command";
381+
if ($this->_exitCode !== 0) {
382+
$this->_error = $this->_stdErr ?
383+
$this->_stdErr :
384+
"Failed without error message: $command (Exit code: {$this->_exitCode})";
367385
return false;
368386
}
369387
} else {

0 commit comments

Comments
 (0)