Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F15333363
D21423.id50976.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
6 KB
Referenced Files
None
Subscribers
None
D21423.id50976.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D21423: Give Futures clearer start/end and exception semantics
Attached
Detach File
Event Timeline
Log In to Comment