Skip to content

Commit 00bb86b

Browse files
fmeumcopybara-github
authored andcommitted
Fix crash on remote-only action template outputs
Fixes the following type of crash when the outputs of an action template are built with BwoB without being downloaded: ``` java.lang.RuntimeException: Unrecoverable error while evaluating node 'TargetCompletionKey{topLevelArtifactContext=com.google.devtools.build.lib.analysis.TopLevelArtifactContext@90504ed, actionLookupKey=ConfiguredTargetKey{label=//a:main, config=BuildConfigurationKey[ace1802e9ffc3691a893a40a89ff0d55ab85b5bb1a265fd1bb830b1af3f3a0e0]}, willTest=false}' (requested by nodes 'BuildDriverKey of ActionLookupKey: ConfiguredTargetKey{label=//a:main, config=BuildConfigurationKey[4e639ef1ee6b55f3683fb1281a60a624b3a6eb2ef19705d98d7e875872945deb]}') at com.google.devtools.build.skyframe.AbstractParallelEvaluator$Evaluate.run(AbstractParallelEvaluator.java:551) at com.google.devtools.build.lib.concurrent.AbstractQueueVisitor$WrappedRunnable.run(AbstractQueueVisitor.java:435) at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.compute(Unknown Source) at java.base/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.compute(Unknown Source) at java.base/java.util.concurrent.ForkJoinTask$InterruptibleTask.exec(Unknown Source) at java.base/java.util.concurrent.ForkJoinTask.doExec(Unknown Source) at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(Unknown Source) at java.base/java.util.concurrent.ForkJoinPool.runWorker(Unknown Source) at java.base/java.util.concurrent.ForkJoinWorkerThread.run(Unknown Source) Caused by: java.lang.IllegalStateException: generating action for artifact File:[[<execution_root>]bazel-out/darwin_arm64-fastbuild/bin]a/_objs/main/dir is not an ActionExecutionMetadata at com.google.common.base.Preconditions.checkState(Preconditions.java:603) at com.google.devtools.build.lib.remote.RemoteImportantOutputHandler.getGeneratingAction(RemoteImportantOutputHandler.java:191) at com.google.devtools.build.lib.remote.RemoteImportantOutputHandler.downloadArtifact(RemoteImportantOutputHandler.java:164) at com.google.devtools.build.lib.remote.RemoteImportantOutputHandler.ensureToplevelArtifacts(RemoteImportantOutputHandler.java:117) at com.google.devtools.build.lib.remote.RemoteImportantOutputHandler.processOutputsAndGetLostArtifacts(RemoteImportantOutputHandler.java:72) at com.google.devtools.build.lib.skyframe.CompletionFunction.informImportantOutputHandler(CompletionFunction.java:431) at com.google.devtools.build.lib.skyframe.CompletionFunction.compute(CompletionFunction.java:327) at com.google.devtools.build.skyframe.AbstractParallelEvaluator$Evaluate.run(AbstractParallelEvaluator.java:471) ``` Closes #26143. PiperOrigin-RevId: 776209213 Change-Id: Id17372a202cab5b57bc9fccfdba53291fd08a91b
1 parent d49967e commit 00bb86b

File tree

2 files changed

+59
-5
lines changed

2 files changed

+59
-5
lines changed

src/main/java/com/google/devtools/build/lib/remote/RemoteImportantOutputHandler.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@
1818
import com.google.common.collect.ImmutableList;
1919
import com.google.common.util.concurrent.ListenableFuture;
2020
import com.google.devtools.build.lib.actions.ActionExecutionMetadata;
21-
import com.google.devtools.build.lib.actions.ActionInput;
2221
import com.google.devtools.build.lib.actions.ActionInputPrefetcher;
2322
import com.google.devtools.build.lib.actions.Actions;
2423
import com.google.devtools.build.lib.actions.Artifact;
2524
import com.google.devtools.build.lib.actions.Artifact.DerivedArtifact;
25+
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
2626
import com.google.devtools.build.lib.actions.FileArtifactValue;
2727
import com.google.devtools.build.lib.actions.ImportantOutputHandler;
2828
import com.google.devtools.build.lib.actions.InputMetadataProvider;
@@ -152,7 +152,7 @@ private void downloadArtifact(
152152
return;
153153
}
154154

155-
var filesToDownload = new ArrayList<ActionInput>(treeArtifactValue.getChildren().size());
155+
var filesToDownload = new ArrayList<TreeFileArtifact>(treeArtifactValue.getChildren().size());
156156
for (var entry : treeArtifactValue.getChildValues().entrySet()) {
157157
if (remoteOutputChecker.shouldDownloadOutput(entry.getKey(), entry.getValue())) {
158158
filesToDownload.add(entry.getKey());
@@ -161,7 +161,9 @@ private void downloadArtifact(
161161
if (!filesToDownload.isEmpty()) {
162162
futures.add(
163163
actionInputPrefetcher.prefetchFiles(
164-
getGeneratingAction(derivedArtifact),
164+
// derivedArtifact's generating action may be an action template, which doesn't
165+
// implement the required ActionExecutionMetadata.
166+
getGeneratingAction(filesToDownload.getFirst()),
165167
filesToDownload,
166168
metadataProvider,
167169
ActionInputPrefetcher.Priority.LOW,
@@ -190,8 +192,9 @@ private ActionExecutionMetadata getGeneratingAction(DerivedArtifact artifact)
190192
var action = Actions.getGeneratingAction(graph, artifact);
191193
Preconditions.checkState(
192194
action instanceof ActionExecutionMetadata,
193-
"generating action for artifact %s is not an ActionExecutionMetadata",
194-
artifact);
195+
"generating action for artifact %s is not an ActionExecutionMetadata, but %s",
196+
artifact,
197+
action != null ? action.getClass() : null);
195198
return (ActionExecutionMetadata) action;
196199
}
197200
}

src/test/shell/bazel/remote/build_without_the_bytes_test.sh

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,57 @@ EOF
571571
fi
572572
}
573573

574+
function test_download_minimal_templated_tree_artifact_downloaded_later() {
575+
mkdir -p a
576+
577+
# We need the top-level output to be a tree artifact generated by a template
578+
# action. This is one way to do that: generate a tree artifact of C++ source
579+
# files, and then compile them with a cc_library / cc_binary rule.
580+
#
581+
# The default top-level output of a cc_binary is the final binary, which is
582+
# not what we want. Instead, we use --output_groups=compilation_outputs to
583+
# fetch the .o files as the top-level outputs.
584+
585+
cat > a/gentree.bzl <<'EOF'
586+
def _gentree(ctx):
587+
out = ctx.actions.declare_directory("dir.cc")
588+
ctx.actions.run_shell(
589+
outputs = [out],
590+
command = "echo 'int main(){return 0;}' > %s/foo.cc" % out.path,
591+
)
592+
return DefaultInfo(files = depset([out]))
593+
594+
gentree = rule(implementation = _gentree)
595+
EOF
596+
597+
cat > a/BUILD <<'EOF'
598+
load(":gentree.bzl", "gentree")
599+
gentree(name = "tree")
600+
cc_binary(name = "main", srcs = [":tree"])
601+
EOF
602+
603+
bazel build \
604+
--remote_executor=grpc://localhost:${worker_port} \
605+
--remote_download_minimal \
606+
--output_groups=compilation_outputs \
607+
//a:main || fail "Failed to build //a:main"
608+
609+
bazel build \
610+
--remote_executor=grpc://localhost:${worker_port} \
611+
--remote_download_toplevel \
612+
--output_groups=compilation_outputs \
613+
//a:main || fail "Failed to build //a:main"
614+
615+
if [[ "$PLATFORM" == "darwin" ]]; then
616+
expected_object_file=bazel-bin/a/_objs/main/dir/foo.o
617+
else
618+
expected_object_file=bazel-bin/a/_pic_objs/main/dir/foo.pic.o
619+
fi
620+
if ! [[ -f "$expected_object_file" ]]; then
621+
fail "Expected toplevel output $expected_object_file to be downloaded"
622+
fi
623+
}
624+
574625
function test_downloads_toplevel_src_runfiles() {
575626
# Test that using --remote_download_toplevel with a non-generated (source)
576627
# runfile dependency works.

0 commit comments

Comments
 (0)