aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java
diff options
context:
space:
mode:
authorGravatar Janak Ramakrishnan <janakr@google.com>2015-10-20 21:41:57 +0000
committerGravatar Han-Wen Nienhuys <hanwen@google.com>2015-10-21 14:39:07 +0000
commit11ef8fc44821fb593a512eb5a3423013abbe39aa (patch)
tree1bc872ff60f4ed96862683dcc76009636f2f34af /src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java
parent84075f3584a2f38b489ed8fbc5da464c95653525 (diff)
Keep track of any RuntimeExceptions thrown during evaluation. Previously, RuntimeExceptions that were thrown after an InterruptedException was thrown would be swallowed.
-- MOS_MIGRATED_REVID=105902192
Diffstat (limited to 'src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java')
-rw-r--r--src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java19
1 files changed, 17 insertions, 2 deletions
diff --git a/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java b/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java
index 243577ecc6..dd2089aa18 100644
--- a/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java
+++ b/src/main/java/com/google/devtools/build/skyframe/ParallelEvaluator.java
@@ -41,7 +41,6 @@ import com.google.devtools.build.skyframe.EvaluationProgressReceiver.EvaluationS
import com.google.devtools.build.skyframe.MemoizingEvaluator.EmittedEventState;
import com.google.devtools.build.skyframe.NodeEntry.DependencyState;
import com.google.devtools.build.skyframe.NodeEntry.DirtyState;
-import com.google.devtools.build.skyframe.Scheduler.SchedulerException;
import com.google.devtools.build.skyframe.SkyFunctionException.ReifiedSkyFunctionException;
import java.util.ArrayDeque;
@@ -596,6 +595,7 @@ public final class ParallelEvaluator implements Evaluator {
private class ValueVisitor extends AbstractQueueVisitor {
private AtomicBoolean preventNewEvaluations = new AtomicBoolean(false);
private final Set<SkyKey> inflightNodes = Sets.newConcurrentHashSet();
+ private final Set<RuntimeException> crashes = Sets.newConcurrentHashSet();
private ValueVisitor(int threadCount) {
super(/*concurrent*/true,
@@ -652,6 +652,14 @@ public final class ParallelEvaluator implements Evaluator {
return preventNewEvaluations.compareAndSet(false, true);
}
+ void noteCrash(RuntimeException e) {
+ crashes.add(e);
+ }
+
+ Collection<RuntimeException> getCrashes() {
+ return crashes;
+ }
+
void notifyDone(SkyKey key) {
inflightNodes.remove(key);
}
@@ -906,7 +914,9 @@ public final class ParallelEvaluator implements Evaluator {
// Programmer error (most likely NPE or a failed precondition in a SkyFunction). Output
// some context together with the exception.
String msg = prepareCrashMessage(skyKey, state.getInProgressReverseDeps());
- throw new RuntimeException(msg, re);
+ RuntimeException ex = new RuntimeException(msg, re);
+ visitor.noteCrash(ex);
+ throw ex;
} finally {
env.doneBuilding();
long elapsedTimeNanos = Profiler.nanoTimeMaybe() - startTime;
@@ -1200,6 +1210,10 @@ public final class ParallelEvaluator implements Evaluator {
try {
visitor.waitForCompletion();
} catch (final SchedulerException e) {
+ if (!visitor.getCrashes().isEmpty()) {
+ reporter.handle(Event.error("Crashes detected: " + visitor.getCrashes()));
+ throw Iterables.getFirst(visitor.getCrashes(), null);
+ }
Throwables.propagateIfPossible(e.getCause(), InterruptedException.class);
if (Thread.interrupted()) {
// As per the contract of AbstractQueueVisitor#work, if an unchecked exception is thrown and
@@ -1228,6 +1242,7 @@ public final class ParallelEvaluator implements Evaluator {
graph.get(errorKey).getValueMaybeWithMetadata()));
}
}
+ Preconditions.checkState(visitor.getCrashes().isEmpty(), visitor.getCrashes());
// Successful evaluation, either because keepGoing or because we actually did succeed.
// TODO(bazel-team): Maybe report root causes during the build for lower latency.