Don't necessarily crash on a missing dep. Instead, pass it to the inconsistency receiver, for better stability while we debug. We should be able to recover from this situation reasonably gracefully.
PiperOrigin-RevId: 229944221
diff --git a/src/main/java/com/google/devtools/build/skyframe/BUILD b/src/main/java/com/google/devtools/build/skyframe/BUILD
index 7de5e27..b1ff51e 100644
--- a/src/main/java/com/google/devtools/build/skyframe/BUILD
+++ b/src/main/java/com/google/devtools/build/skyframe/BUILD
@@ -40,6 +40,7 @@
"//src/main/java/com/google/devtools/build/lib/profiler",
"//src/main/java/com/google/devtools/build/lib/skyframe/serialization/autocodec",
"//src/main/java/com/google/devtools/common/options",
+ "//third_party:flogger",
"//third_party:guava",
"//third_party:jsr305",
],
diff --git a/src/main/java/com/google/devtools/build/skyframe/GraphInconsistencyReceiver.java b/src/main/java/com/google/devtools/build/skyframe/GraphInconsistencyReceiver.java
index 9f0d5cc..d43a163 100644
--- a/src/main/java/com/google/devtools/build/skyframe/GraphInconsistencyReceiver.java
+++ b/src/main/java/com/google/devtools/build/skyframe/GraphInconsistencyReceiver.java
@@ -32,7 +32,8 @@
RESET_REQUESTED,
CHILD_MISSING_FOR_DIRTY_NODE, // TODO(mschaller): put "parent" before "child" for consistency
PARENT_FORCE_REBUILD_OF_CHILD,
- BUILDING_PARENT_FOUND_UNDONE_CHILD
+ BUILDING_PARENT_FOUND_UNDONE_CHILD,
+ ALREADY_DECLARED_CHILD_MISSING
}
/** A {@link GraphInconsistencyReceiver} that crashes on any inconsistency. */
diff --git a/src/main/java/com/google/devtools/build/skyframe/SkyFunctionEnvironment.java b/src/main/java/com/google/devtools/build/skyframe/SkyFunctionEnvironment.java
index 9c45ef6..a84ab55 100644
--- a/src/main/java/com/google/devtools/build/skyframe/SkyFunctionEnvironment.java
+++ b/src/main/java/com/google/devtools/build/skyframe/SkyFunctionEnvironment.java
@@ -20,6 +20,7 @@
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
+import com.google.common.flogger.GoogleLogger;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
@@ -49,6 +50,8 @@
/** A {@link SkyFunction.Environment} implementation for {@link ParallelEvaluator}. */
class SkyFunctionEnvironment extends AbstractSkyFunctionEnvironment {
+ private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();
+
private static final SkyValue NULL_MARKER = new SkyValue() {};
private static final boolean PREFETCH_OLD_DEPS =
Boolean.parseBoolean(
@@ -166,7 +169,7 @@
this.bubbleErrorInfo = null;
this.hermeticity = skyKey.functionName().getHermeticity();
this.previouslyRequestedDepsValues =
- batchPrefetch(skyKey, directDeps, oldDeps, /*assertDone=*/ true, skyKey);
+ batchPrefetch(skyKey, directDeps, oldDeps, /*assertDone=*/ true);
Preconditions.checkState(
!this.previouslyRequestedDepsValues.containsKey(ErrorTransienceValue.KEY),
"%s cannot have a dep on ErrorTransienceValue during building",
@@ -188,7 +191,7 @@
this.hermeticity = skyKey.functionName().getHermeticity();
try {
this.previouslyRequestedDepsValues =
- batchPrefetch(skyKey, directDeps, oldDeps, /*assertDone=*/ false, skyKey);
+ batchPrefetch(skyKey, directDeps, oldDeps, /*assertDone=*/ false);
} catch (UndonePreviouslyRequestedDep undonePreviouslyRequestedDep) {
throw new IllegalStateException(
"batchPrefetch can't throw UndonePreviouslyRequestedDep unless assertDone is true",
@@ -201,11 +204,7 @@
}
private Map<SkyKey, SkyValue> batchPrefetch(
- SkyKey requestor,
- GroupedList<SkyKey> depKeys,
- Set<SkyKey> oldDeps,
- boolean assertDone,
- SkyKey keyForDebugging)
+ SkyKey requestor, GroupedList<SkyKey> depKeys, Set<SkyKey> oldDeps, boolean assertDone)
throws InterruptedException, UndonePreviouslyRequestedDep {
QueryableGraph.PrefetchDepsRequest request = null;
if (PREFETCH_OLD_DEPS) {
@@ -224,16 +223,19 @@
try {
inFlightEntry = evaluatorContext.getGraph().get(null, Reason.OTHER, requestor);
} catch (InterruptedException e) {
+ logger.atWarning().withCause(e).log(
+ "Interrupted while getting parent entry for %s for crash", requestor);
// We're crashing, don't mask it.
Thread.currentThread().interrupt();
}
- throw new IllegalStateException(
- "Missing keys for "
- + keyForDebugging
- + ": "
- + Sets.difference(depKeys.toSet(), batchMap.keySet())
- + "\n\n"
- + inFlightEntry);
+ Set<SkyKey> difference = Sets.difference(depKeys.toSet(), batchMap.keySet());
+ logger.atSevere().log("Missing keys for %s: %s\n\n%s", requestor, difference, inFlightEntry);
+ for (SkyKey missingDep : difference) {
+ evaluatorContext
+ .getGraphInconsistencyReceiver()
+ .noteInconsistencyAndMaybeThrow(
+ requestor, missingDep, Inconsistency.ALREADY_DECLARED_CHILD_MISSING);
+ }
}
ImmutableMap.Builder<SkyKey, SkyValue> depValuesBuilder =
ImmutableMap.builderWithExpectedSize(batchMap.size());