Page MenuHomePhabricator

D11688.id28199.diff
No OneTemporary

D11688.id28199.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
@@ -48,6 +48,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
@@ -245,6 +249,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 )------------------------------------------ */
@@ -678,13 +697,50 @@
} else {
$trap = null;
}
+
+ $stdout_target = null;
+ $stderr_target = 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(
+ '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(
+ 'Unable to open temporary files for '.
+ 'reading Windows stdout / stderr streams');
+ }
+ }
if ($trap) {
$err = $trap->getErrorsAsString();
@@ -701,12 +757,12 @@
$this->proc = $proc;
list($stdin, $stdout, $stderr) = $pipes;
-
+
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)) ||
@@ -748,14 +804,14 @@
$status = $this->procGetStatus();
$read_buffer_size = $this->readBufferSize;
-
+
$max_stdout_read_bytes = PHP_INT_MAX;
$max_stderr_read_bytes = PHP_INT_MAX;
if ($read_buffer_size !== null) {
$max_stdout_read_bytes = $read_buffer_size - strlen($this->stdout);
$max_stderr_read_bytes = $read_buffer_size - strlen($this->stderr);
}
-
+
if ($max_stdout_read_bytes > 0) {
$this->stdout .= $this->readAndDiscard(
$stdout,
@@ -787,8 +843,13 @@
$max_stderr_read_bytes);
}
}
-
+
if (!$status['running']) {
+ if ($this->useWindowsFileStreams) {
+ fclose($stdout);
+ fclose($stderr);
+ }
+
$this->result = array(
$status['exitcode'],
$this->stdout,

File Metadata

Mime Type
text/plain
Expires
Tue, Apr 1, 11:56 PM (5 d, 2 h ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7704654
Default Alt Text
D11688.id28199.diff (3 KB)

Event Timeline