Page MenuHomePhabricator

D21423.id50976.diff
No OneTemporary

D21423.id50976.diff

diff --git a/src/future/Future.php b/src/future/Future.php
--- a/src/future/Future.php
+++ b/src/future/Future.php
@@ -14,6 +14,7 @@
private $exception;
private $futureKey;
private $serviceProfilerCallID;
+ private $raiseExceptionOnStart = true;
private static $nextKey = 1;
/**
@@ -41,7 +42,7 @@
'timeout.'));
}
- if (!$this->hasResult() && !$this->hasException()) {
+ if (!$this->canResolve()) {
$graph = new FutureIterator(array($this));
$graph->resolveAll();
}
@@ -53,25 +54,8 @@
return $this->getResult();
}
- final public function startFuture() {
- if ($this->hasStarted) {
- throw new Exception(
- pht(
- 'Future has already started; futures can not start more '.
- 'than once.'));
- }
- $this->hasStarted = true;
-
- $this->startServiceProfiler();
- $this->updateFuture();
- }
-
final public function updateFuture() {
- if ($this->hasException()) {
- return;
- }
-
- if ($this->hasResult()) {
+ if ($this->canResolve()) {
return;
}
@@ -84,25 +68,6 @@
}
}
- final public function endFuture() {
- if (!$this->hasException() && !$this->hasResult()) {
- throw new Exception(
- pht(
- 'Trying to end a future which has no exception and no result. '.
- 'Futures must resolve before they can be ended.'));
- }
-
- if ($this->hasEnded) {
- throw new Exception(
- pht(
- 'Future has already ended; futures can not end more '.
- 'than once.'));
- }
- $this->hasEnded = true;
-
- $this->endServiceProfiler();
- }
-
private function startServiceProfiler() {
// NOTE: This is a soft dependency so that we don't need to build the
@@ -181,7 +146,24 @@
}
public function start() {
- $this->isReady();
+ if ($this->hasStarted) {
+ throw new Exception(
+ pht(
+ 'Future has already started; futures can not start more '.
+ 'than once.'));
+ }
+ $this->hasStarted = true;
+
+ $this->startServiceProfiler();
+
+ $this->updateFuture();
+
+ if ($this->raiseExceptionOnStart) {
+ if ($this->hasException()) {
+ throw $this->getException();
+ }
+ }
+
return $this;
}
@@ -212,6 +194,8 @@
$this->hasResult = true;
$this->result = $result;
+ $this->endFuture();
+
return $this;
}
@@ -219,13 +203,16 @@
return $this->hasResult;
}
- final private function setException($exception) {
+ private function setException($exception) {
// NOTE: The parameter may be an Exception or a Throwable.
$this->exception = $exception;
+
+ $this->endFuture();
+
return $this;
}
- final private function getException() {
+ private function getException() {
return $this->exception;
}
@@ -254,4 +241,37 @@
return $this->futureKey;
}
+ final public function setRaiseExceptionOnStart($raise) {
+ $this->raiseExceptionOnStart = $raise;
+ return $this;
+ }
+
+ final public function getHasFutureStarted() {
+ return $this->hasStarted;
+ }
+
+ final public function canResolve() {
+ if ($this->hasResult()) {
+ return true;
+ }
+
+ if ($this->hasException()) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private function endFuture() {
+ if ($this->hasEnded) {
+ throw new Exception(
+ pht(
+ 'Future has already ended; futures can not end more '.
+ 'than once.'));
+ }
+ $this->hasEnded = true;
+
+ $this->endServiceProfiler();
+ }
+
}
diff --git a/src/future/FutureIterator.php b/src/future/FutureIterator.php
--- a/src/future/FutureIterator.php
+++ b/src/future/FutureIterator.php
@@ -222,12 +222,7 @@
$resolve_key = null;
foreach ($working_set as $future_key => $future) {
- if ($future->hasException()) {
- $resolve_key = $future_key;
- break;
- }
-
- if ($future->hasResult()) {
+ if ($future->canResolve()) {
$resolve_key = $future_key;
break;
}
@@ -393,7 +388,13 @@
unset($this->wait[$future_key]);
$this->work[$future_key] = $future_key;
- $this->futures[$future_key]->startFuture();
+ $future = $this->futures[$future_key];
+
+ if (!$future->getHasFutureStarted()) {
+ $future
+ ->setRaiseExceptionOnStart(false)
+ ->start();
+ }
}
private function moveFutureToDone($future_key) {
@@ -404,8 +405,6 @@
// futures that are ready to go as soon as we can.
$this->updateWorkingSet();
-
- $this->futures[$future_key]->endFuture();
}
/**
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
@@ -95,6 +95,18 @@
return $status['pid'];
}
+ public function hasPID() {
+ if ($this->procStatus) {
+ return true;
+ }
+
+ if ($this->proc) {
+ return true;
+ }
+
+ return false;
+ }
+
/* -( Configuring Execution )---------------------------------------------- */
@@ -194,7 +206,7 @@
public function readStdout() {
if ($this->start) {
- $this->isReady(); // Sync
+ $this->updateFuture(); // Sync
}
$result = (string)substr($this->stdout, $this->stdoutPos);
@@ -890,6 +902,17 @@
return $this->procStatus;
}
}
+
+ // See T13555. This may occur if you call "getPID()" on a future which
+ // exited immediately without ever creating a valid subprocess.
+
+ if (!$this->proc) {
+ throw new Exception(
+ pht(
+ 'Attempting to get subprocess status in "ExecFuture" with no '.
+ 'valid subprocess.'));
+ }
+
$this->procStatus = proc_get_status($this->proc);
return $this->procStatus;
diff --git a/src/repository/graph/query/ArcanistGitCommitGraphQuery.php b/src/repository/graph/query/ArcanistGitCommitGraphQuery.php
--- a/src/repository/graph/query/ArcanistGitCommitGraphQuery.php
+++ b/src/repository/graph/query/ArcanistGitCommitGraphQuery.php
@@ -104,7 +104,7 @@
}
$future = array_pop($this->futures);
- $future->startFuture();
+ $future->start();
$iterator = id(new LinesOfALargeExecFuture($future))
->setDelimiter("\1");

File Metadata

Mime Type
text/plain
Expires
Sun, Mar 9, 2:03 AM (1 w, 6 d ago)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
7384100
Default Alt Text
D21423.id50976.diff (6 KB)

Event Timeline