Make the server commit suicide if its PID file vanishes.

--
PiperOrigin-RevId: 144434688
MOS_MIGRATED_REVID=144434688
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 532923c..434d099 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
@@ -120,6 +120,7 @@
   private final Iterable<BlazeModule> blazeModules;
   private final Map<String, BlazeCommand> commandMap = new LinkedHashMap<>();
   private final Clock clock;
+  private final Runnable abruptShutdownHandler;
 
   private final PackageFactory packageFactory;
   private final ConfigurationFactory configurationFactory;
@@ -155,6 +156,7 @@
       ConfigurationFactory configurationFactory,
       ImmutableMap<String, InfoItem> infoItems,
       Clock clock,
+      Runnable abruptShutdownHandler,
       OptionsProvider startupOptionsProvider,
       Iterable<BlazeModule> blazeModules,
       SubscriberExceptionHandler eventBusExceptionHandler,
@@ -174,6 +176,7 @@
     this.configurationFactory = configurationFactory;
     this.infoItems = infoItems;
     this.clock = clock;
+    this.abruptShutdownHandler = abruptShutdownHandler;
     this.startupOptionsProvider = startupOptionsProvider;
     this.queryEnvironmentFactory = queryEnvironmentFactory;
     this.queryFunctions = queryFunctions;
@@ -481,6 +484,12 @@
     }
   }
 
+  public void prepareForAbruptShutdown() {
+    if (abruptShutdownHandler != null) {
+      abruptShutdownHandler.run();
+    }
+  }
+
   /** Invokes {@link BlazeModule#blazeShutdownOnCrash()} on all registered modules. */
   public void shutdownOnCrash() {
     for (BlazeModule module : blazeModules) {
@@ -728,7 +737,7 @@
 
     BlazeRuntime runtime;
     try {
-      runtime = newRuntime(modules, commandLineOptions.getStartupArgs());
+      runtime = newRuntime(modules, commandLineOptions.getStartupArgs(), null);
     } catch (OptionsParsingException e) {
       OutErr.SYSTEM_OUT_ERR.printErr(e.getMessage());
       return ExitCode.COMMAND_LINE_ERROR.getNumericExitCode();
@@ -814,7 +823,15 @@
   private static RPCServer createBlazeRPCServer(
       Iterable<BlazeModule> modules, List<String> args)
       throws IOException, OptionsParsingException, AbruptExitException {
-    BlazeRuntime runtime = newRuntime(modules, args);
+    final RPCServer[] rpcServer = new RPCServer[1];
+    Runnable prepareForAbruptShutdown = new Runnable() {
+      @Override
+      public void run() {
+        rpcServer[0].prepareForAbruptShutdown();
+      }
+    };
+
+    BlazeRuntime runtime = newRuntime(modules, args, prepareForAbruptShutdown);
     BlazeCommandDispatcher dispatcher = new BlazeCommandDispatcher(runtime);
     CommandExecutor commandExecutor = new CommandExecutor(runtime, dispatcher);
 
@@ -825,13 +842,15 @@
       // gRPC server is not compiled in so that we don't need gRPC for bootstrapping.
       Class<?> factoryClass = Class.forName(
           "com.google.devtools.build.lib.server.GrpcServerImpl$Factory");
-    RPCServer.Factory factory = (RPCServer.Factory) factoryClass.getConstructor().newInstance();
-    return factory.create(commandExecutor, runtime.getClock(),
-        startupOptions.commandPort, runtime.getServerDirectory(),
-        startupOptions.maxIdleSeconds);
+      RPCServer.Factory factory = (RPCServer.Factory) factoryClass.getConstructor().newInstance();
+      rpcServer[0] = factory.create(commandExecutor, runtime.getClock(),
+          startupOptions.commandPort, runtime.getServerDirectory(),
+          startupOptions.maxIdleSeconds);
+      return rpcServer[0];
     } catch (ReflectiveOperationException | IllegalArgumentException e) {
       throw new AbruptExitException("gRPC server not compiled in", ExitCode.BLAZE_INTERNAL_ERROR);
     }
+
   }
 
   private static Function<String, String> sourceFunctionForMap(final Map<String, String> map) {
@@ -890,7 +909,8 @@
    *         an error string that, if not null, describes a fatal initialization failure that makes
    *         this runtime unsuitable for real commands
    */
-  private static BlazeRuntime newRuntime(Iterable<BlazeModule> blazeModules, List<String> args)
+  private static BlazeRuntime newRuntime(Iterable<BlazeModule> blazeModules, List<String> args,
+      Runnable abruptShutdownHandler)
       throws AbruptExitException, OptionsParsingException {
     OptionsProvider options = parseOptions(blazeModules, args);
     for (BlazeModule module : blazeModules) {
@@ -951,6 +971,7 @@
         .setServerDirectories(serverDirectories)
         .setStartupOptionsProvider(options)
         .setClock(clock)
+        .setAbruptShutdownHandler(abruptShutdownHandler)
         // TODO(bazel-team): Make BugReportingExceptionHandler the default.
         // See bug "Make exceptions in EventBus subscribers fatal"
         .setEventBusExceptionHandler(
@@ -1058,6 +1079,7 @@
   public static class Builder {
     private ServerDirectories serverDirectories;
     private Clock clock;
+    private Runnable abruptShutdownHandler;
     private OptionsProvider startupOptionsProvider;
     private final List<BlazeModule> blazeModules = new ArrayList<>();
     private SubscriberExceptionHandler eventBusExceptionHandler = new RemoteExceptionHandler();
@@ -1138,6 +1160,7 @@
           configurationFactory,
           serverBuilder.getInfoItems(),
           clock,
+          abruptShutdownHandler,
           startupOptionsProvider,
           ImmutableList.copyOf(blazeModules),
           eventBusExceptionHandler,
@@ -1162,6 +1185,11 @@
       return this;
     }
 
+    public Builder setAbruptShutdownHandler(Runnable handler) {
+      this.abruptShutdownHandler = handler;
+      return this;
+    }
+
     public Builder setStartupOptionsProvider(OptionsProvider startupOptionsProvider) {
       this.startupOptionsProvider = startupOptionsProvider;
       return this;