From ed0c5f892aee9b08a20184d2997d1b9b59575801 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 7 Mar 2024 08:01:10 -0800 Subject: [PATCH] Fix CommandLine class initialization deadlock. https://github.com/bazelbuild/bazel/issues/21566#issuecomment-1983242695 shows a deadlock when initializing static variable `CommandLine.EMPTY` and another thread is initializing `CommandLine`'s subclass `AbstractCommandLine` because `CommandLine.EMPTY` is an instance of `AbstractCommandLine`. Fixes https://github.com/bazelbuild/bazel/issues/21566. --- .../google/devtools/build/lib/actions/CommandLine.java | 10 +++++++--- .../devtools/build/lib/analysis/RunfilesSupport.java | 4 ++-- .../analysis/starlark/StarlarkCustomCommandLine.java | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/actions/CommandLine.java b/src/main/java/com/google/devtools/build/lib/actions/CommandLine.java index 22e0f8a7792870..6db5b0470d80c7 100644 --- a/src/main/java/com/google/devtools/build/lib/actions/CommandLine.java +++ b/src/main/java/com/google/devtools/build/lib/actions/CommandLine.java @@ -25,11 +25,13 @@ /** A representation of a list of arguments. */ public abstract class CommandLine { - public static final CommandLine EMPTY = new EmptyCommandLine(); + public static CommandLine empty() { + return EmptyCommandLine.INSTANCE; + } /** Returns a {@link CommandLine} backed by the given list of arguments. */ public static CommandLine of(ImmutableList arguments) { - return arguments.isEmpty() ? CommandLine.EMPTY : new SimpleCommandLine(arguments); + return arguments.isEmpty() ? empty() : new SimpleCommandLine(arguments); } /** @@ -40,7 +42,7 @@ public static CommandLine concat(CommandLine commandLine, ImmutableList if (args.isEmpty()) { return commandLine; } - if (commandLine == EMPTY) { + if (commandLine == EmptyCommandLine.INSTANCE) { return CommandLine.of(args); } return new SuffixedCommandLine(args, commandLine); @@ -126,6 +128,8 @@ public abstract void addToFingerprint( throws CommandLineExpansionException, InterruptedException; private static final class EmptyCommandLine extends AbstractCommandLine { + private static final EmptyCommandLine INSTANCE = new EmptyCommandLine(); + @Override public ImmutableList arguments() { return ImmutableList.of(); diff --git a/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java b/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java index dca5aea79149c1..58fbae4373cfdc 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/RunfilesSupport.java @@ -526,10 +526,10 @@ private static CommandLine computeArgs(RuleContext ruleContext) throws Interrupt if (!ruleContext.getRule().isAttrDefined("args", Type.STRING_LIST)) { // Some non-_binary rules create RunfilesSupport instances; it is fine to not have an args // attribute here. - return CommandLine.EMPTY; + return CommandLine.empty(); } ImmutableList args = ruleContext.getExpander().withDataLocations().tokenized("args"); - return args.isEmpty() ? CommandLine.EMPTY : CommandLine.of(args); + return args.isEmpty() ? CommandLine.empty() : CommandLine.of(args); } private static ActionEnvironment computeActionEnvironment(RuleContext ruleContext) diff --git a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkCustomCommandLine.java b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkCustomCommandLine.java index be3079f48a0785..5562e5026bbb00 100644 --- a/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkCustomCommandLine.java +++ b/src/main/java/com/google/devtools/build/lib/analysis/starlark/StarlarkCustomCommandLine.java @@ -756,7 +756,7 @@ Builder addFormatted(Object object, String format) { CommandLine build(boolean flagPerLine) { if (arguments.isEmpty()) { - return CommandLine.EMPTY; + return CommandLine.empty(); } Object[] args = arguments.toArray(); return flagPerLine