diff options
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.java | 36 |
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 "; |