From e905ec3b99dd98c2c99929a6cda0b99cca328c24 Mon Sep 17 00:00:00 2001 From: Janak Ramakrishnan Date: Tue, 30 Jun 2015 20:16:32 +0000 Subject: Relax invariant that an action's inputs discovered during execution must be included in the action's inputs as found during the input discovery phase. We still require that no new metadata be discovered -- in other words, the "new" inputs are likely just symlinks to old inputs, with different nominal paths. -- MOS_MIGRATED_REVID=97257026 --- .../lib/skyframe/ActionExecutionFunction.java | 35 +++++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java index 5b5c8ead04..ae58479d3d 100644 --- a/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java +++ b/src/main/java/com/google/devtools/build/lib/skyframe/ActionExecutionFunction.java @@ -17,6 +17,7 @@ import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.base.Predicates; import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -318,7 +319,6 @@ public class ActionExecutionFunction implements SkyFunction, CompletionReceiver // This may be recreated if we discover inputs. PerActionFileCache perActionFileCache = new PerActionFileCache(state.inputArtifactData); ActionExecutionContext actionExecutionContext = null; - boolean inputsDiscoveredDuringActionExecution = false; try { if (action.discoversInputs()) { if (!state.hasDiscoveredInputs()) { @@ -329,11 +329,6 @@ public class ActionExecutionFunction implements SkyFunction, CompletionReceiver Preconditions.checkState(env.valuesMissing(), action); return null; } - if (state.discoveredInputs == null) { - // Action had nothing to tell us about discovered inputs before execution. We'll have to - // add them afterwards. - inputsDiscoveredDuringActionExecution = true; - } } // state.discoveredInputs can be null even after include scanning if action discovers them // during execution. @@ -366,10 +361,34 @@ public class ActionExecutionFunction implements SkyFunction, CompletionReceiver } } } - if (inputsDiscoveredDuringActionExecution) { + if (action.discoversInputs()) { Map metadataFoundDuringActionExecution = declareAdditionalDependencies(env, action, state.inputArtifactData.keySet()); - state.discoveredInputs = metadataFoundDuringActionExecution.keySet(); + if (state.discoveredInputs == null) { + // Include scanning didn't find anything beforehand -- these are the definitive discovered + // inputs. + state.discoveredInputs = metadataFoundDuringActionExecution.keySet(); + } else { + // Sadly, even if we discovered inputs, sometimes the action runs and discovers more inputs. + // Technically, this means our pre-execution input discovery is buggy, but it turns out this + // is impractical to fix. + // Any new inputs should already have been built -- this is a check that our input + // discovery code is not missing too much. It may have to be removed if further input + // discovery quirks are found. + Preconditions.checkState(!env.valuesMissing(), "%s %s %s", + action, metadataFoundDuringActionExecution, state); + Set knownMetadata = + ImmutableSet.copyOf(state.inputArtifactData.values()); + ImmutableSet.Builder discoveredInputBuilder = + ImmutableSet.builder().addAll(state.discoveredInputs); + for (Map.Entry entry : + metadataFoundDuringActionExecution.entrySet()) { + Preconditions.checkState(knownMetadata.contains(entry.getValue()), + "%s %s", action, entry); + discoveredInputBuilder.add(entry.getKey()); + } + state.discoveredInputs = discoveredInputBuilder.build(); + } if (env.valuesMissing()) { return null; } -- cgit v1.2.3