Page MenuHomePhabricator

D11688.diff
No OneTemporary

D11688.diff

diff --git a/src/future/exec/ExecFuture.php b/src/future/exec/ExecFuture.php
--- a/src/future/exec/ExecFuture.php
+++ b/src/future/exec/ExecFuture.php
@@ -45,6 +45,10 @@
private $profilerCallID;
private $killedByTimeout;
+ private $useWindowsFileStreams = false;
+ private $windowsStdoutTempFile = null;
+ private $windowsStderrTempFile = null;
+
private static $descriptorSpec = array(
0 => array('pipe', 'r'), // stdin
1 => array('pipe', 'w'), // stdout
@@ -229,6 +233,21 @@
}
+ /**
+ * Set whether to use non-blocking streams on Windows.
+ *
+ * @param bool Whether to use non-blocking streams.
+ * @return this
+ * @task config
+ */
+ public function setUseWindowsFileStreams($use_streams) {
+ if (phutil_is_windows()) {
+ $this->useWindowsFileStreams = $use_streams;
+ }
+ return $this;
+ }
+
+
/* -( Interacting With Commands )------------------------------------------ */
@@ -663,13 +682,47 @@
$trap = null;
}
+ $spec = self::$descriptorSpec;
+ if ($this->useWindowsFileStreams) {
+ $this->windowsStdoutTempFile = new TempFile();
+ $this->windowsStderrTempFile = new TempFile();
+
+ $spec = array(
+ 0 => self::$descriptorSpec[0], // stdin
+ 1 => fopen($this->windowsStdoutTempFile, 'wb'), // stdout
+ 2 => fopen($this->windowsStderrTempFile, 'wb'), // stderr
+ );
+
+ if (!$spec[1] || !$spec[2]) {
+ throw new Exception(pht(
+ 'Unable to create temporary files for '.
+ 'Windows stdout / stderr streams'));
+ }
+ }
+
$proc = @proc_open(
$unmasked_command,
- self::$descriptorSpec,
+ $spec,
$pipes,
$cwd,
$env);
+ if ($this->useWindowsFileStreams) {
+ fclose($spec[1]);
+ fclose($spec[2]);
+ $pipes = array(
+ 0 => head($pipes), // stdin
+ 1 => fopen($this->windowsStdoutTempFile, 'rb'), // stdout
+ 2 => fopen($this->windowsStderrTempFile, 'rb'), // stderr
+ );
+
+ if (!$pipes[1] || !$pipes[2]) {
+ throw new Exception(pht(
+ 'Unable to open temporary files for '.
+ 'reading Windows stdout / stderr streams'));
+ }
+ }
+
if ($trap) {
$err = $trap->getErrorsAsString();
$trap->destroy();
@@ -688,9 +741,9 @@
if (!phutil_is_windows()) {
- // On Windows, there's no such thing as nonblocking interprocess I/O.
- // Just leave the sockets blocking and hope for the best. Some features
- // will not work.
+ // On Windows, we redirect process standard output and standard error
+ // through temporary files, and then use stream_select to determine
+ // if there's more data to read.
if ((!stream_set_blocking($stdout, false)) ||
(!stream_set_blocking($stderr, false)) ||
@@ -757,6 +810,11 @@
}
if (!$status['running']) {
+ if ($this->useWindowsFileStreams) {
+ fclose($stdout);
+ fclose($stderr);
+ }
+
$this->result = array(
$status['exitcode'],
$this->stdout,

File Metadata

Mime Type
text/plain
Expires
Thu, May 9, 4:59 AM (4 w, 1 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6269419
Default Alt Text
D11688.diff (3 KB)

Event Timeline