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");