aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java36
1 files changed, 36 insertions, 0 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
index 6932d9ea18..dab37d82cb 100644
--- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
+++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeRuntime.java
@@ -30,6 +30,7 @@ import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.ServerDirectories;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.ConfigurationFragmentFactory;
+import com.google.devtools.build.lib.analysis.skylark.SkylarkActionFactory;
import com.google.devtools.build.lib.analysis.test.CoverageReportActionFactory;
import com.google.devtools.build.lib.buildeventstream.PathConverter;
import com.google.devtools.build.lib.buildtool.BuildRequestOptions;
@@ -1073,11 +1074,46 @@ public final class BlazeRuntime {
runtime.initWorkspace(directories, binTools);
CustomExitCodePublisher.setAbruptExitStatusFileDir(serverDirectories.getOutputBase());
+ // Most static initializers for @SkylarkSignature-containing classes have already run by this
+ // point, but this will pick up the stragglers.
+ initSkylarkBuiltinsRegistry();
+
AutoProfiler.setClock(runtime.getClock());
BugReport.setRuntime(runtime);
return runtime;
}
+ /**
+ * Configures the Skylark builtins registry.
+ *
+ * <p>Any class containing {@link SkylarkSignature}-annotated fields should call
+ * {@link SkylarkSignatureProcessor#configureSkylarkFunctions} on itself. This serves two
+ * purposes: 1) it initializes those fields for use, and 2) it registers them with the Skylark
+ * builtins registry object
+ * ({@link com.google.devtools.build.lib.syntax.Runtime#getBuiltinRegistry}). Unfortunately
+ * there's some technical debt here: The registry object is static and the registration occurs
+ * inside static initializer blocks.
+ *
+ * <p>The registry supports concurrent read/write access, but read access is not actually
+ * efficient (lockless) until write access is disallowed by calling its
+ * {@link com.google.devtools.build.lib.syntax.Runtime.BuiltinRegistry#freeze freeze} method.
+ * We want to freeze before the build begins, but not before all classes have had a chance to run
+ * their static initializers.
+ *
+ * <p>Therefore, this method first ensures that the initializers have run, and then explicitly
+ * freezes the registry. It ensures initialization by calling a no-op static method on the class.
+ * Only classes whose initializers have been observed to cause {@code BuiltinRegistry} to throw an
+ * exception need to be included here, since that indicates that their initialization did not
+ * happen by this point in time.
+ *
+ * <p>Unit tests don't need to worry about registry freeze exceptions, since the registry isn't
+ * frozen at all for them. They just pay the cost of extra synchronization on every access.
+ */
+ private static void initSkylarkBuiltinsRegistry() {
+ SkylarkActionFactory.forceStaticInitialization();
+ com.google.devtools.build.lib.syntax.Runtime.getBuiltinRegistry().freeze();
+ }
+
private static String maybeGetPidString() {
Integer pid = maybeForceJNIByGettingPid(null);
return pid == null ? "" : "pid " + pid + " and ";