diff options
Diffstat (limited to 'src/main')
4 files changed, 62 insertions, 10 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 25231366f6..733ecfa823 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 @@ -900,7 +900,8 @@ public final class BlazeRuntime { "com.google.devtools.build.lib.server.GrpcServerImpl$Factory"); RPCServer.Factory factory = (RPCServer.Factory) factoryClass.newInstance(); return factory.create(commandExecutor, runtime.getClock(), - startupOptions.commandPort, runtime.getServerDirectory()); + startupOptions.commandPort, runtime.getServerDirectory(), + startupOptions.maxIdleSeconds); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) { throw new AbruptExitException("gRPC server not compiled in", ExitCode.BLAZE_INTERNAL_ERROR); } diff --git a/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java b/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java index b1d1b65545..786d8b3545 100644 --- a/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java +++ b/src/main/java/com/google/devtools/build/lib/runtime/BlazeServerStartupOptions.java @@ -136,10 +136,9 @@ public class BlazeServerStartupOptions extends OptionsBase { @Option(name = "max_idle_secs", defaultValue = "" + (3 * 3600), // NOTE: purely decorative! See class docstring. category = "server startup", - help = "The number of seconds the build server will wait idling " + - "before shutting down. Note: Blaze will ignore this option " + - "unless you are starting a new instance. See also 'blaze help " + - "shutdown'.") + help = "The number of seconds the build server will wait idling before shutting down. Zero " + + "means that the server will never shutdown Note: Blaze will ignore this option " + + "unless you are starting a new instance. See also 'blaze help shutdown'.") public int maxIdleSeconds; @Option(name = "batch", diff --git a/src/main/java/com/google/devtools/build/lib/server/GrpcServerImpl.java b/src/main/java/com/google/devtools/build/lib/server/GrpcServerImpl.java index cd6c68d116..f740c9e57d 100644 --- a/src/main/java/com/google/devtools/build/lib/server/GrpcServerImpl.java +++ b/src/main/java/com/google/devtools/build/lib/server/GrpcServerImpl.java @@ -14,6 +14,7 @@ package com.google.devtools.build.lib.server; +import com.google.common.base.Verify; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.devtools.build.lib.runtime.BlazeCommandDispatcher.LockingMode; @@ -74,6 +75,7 @@ public class GrpcServerImpl extends RPCServer implements CommandServerGrpc.Comma id = UUID.randomUUID().toString(); synchronized (runningCommands) { runningCommands.put(id, this); + runningCommands.notify(); } } @@ -81,6 +83,7 @@ public class GrpcServerImpl extends RPCServer implements CommandServerGrpc.Comma public void close() { synchronized (runningCommands) { runningCommands.remove(id); + runningCommands.notify(); } } } @@ -91,8 +94,8 @@ public class GrpcServerImpl extends RPCServer implements CommandServerGrpc.Comma public static class Factory implements RPCServer.Factory { @Override public RPCServer create(CommandExecutor commandExecutor, Clock clock, int port, - Path serverDirectory) throws IOException { - return new GrpcServerImpl(commandExecutor, clock, port, serverDirectory); + Path serverDirectory, int maxIdleSeconds) throws IOException { + return new GrpcServerImpl(commandExecutor, clock, port, serverDirectory, maxIdleSeconds); } } @@ -151,18 +154,20 @@ public class GrpcServerImpl extends RPCServer implements CommandServerGrpc.Comma private final String requestCookie; private final String responseCookie; private final AtomicLong interruptCounter = new AtomicLong(0); + private final int maxIdleSeconds; private Server server; private int port; // mutable so that we can overwrite it if port 0 is passed in boolean serving; public GrpcServerImpl(CommandExecutor commandExecutor, Clock clock, int port, - Path serverDirectory) throws IOException { + Path serverDirectory, int maxIdleSeconds) throws IOException { super(serverDirectory); this.commandExecutor = commandExecutor; this.clock = clock; this.serverDirectory = serverDirectory; this.port = port; + this.maxIdleSeconds = maxIdleSeconds; this.serving = false; SecureRandom random = new SecureRandom(); @@ -211,6 +216,42 @@ public class GrpcServerImpl extends RPCServer implements CommandServerGrpc.Comma interruptWatcherThread.start(); } + private void timeoutThread() { + synchronized (runningCommands) { + boolean idle = runningCommands.isEmpty(); + boolean wasIdle = false; + long shutdownTime = -1; + + while (true) { + if (!wasIdle && idle) { + shutdownTime = System.currentTimeMillis() + ((long) maxIdleSeconds) * 1000; + } + + try { + if (idle) { + Verify.verify(shutdownTime > 0); + long waitTime = shutdownTime - System.currentTimeMillis(); + if (waitTime > 0) { + runningCommands.wait(waitTime); + } + } else { + runningCommands.wait(); + } + } catch (InterruptedException e) { + // Dealt with by checking the current time below. + } + + wasIdle = idle; + idle = runningCommands.isEmpty(); + if (wasIdle && idle && System.currentTimeMillis() >= shutdownTime) { + break; + } + } + } + + server.shutdownNow(); + } + @Override public void interrupt() { synchronized (runningCommands) { @@ -231,6 +272,17 @@ public class GrpcServerImpl extends RPCServer implements CommandServerGrpc.Comma .build(); server.start(); + if (maxIdleSeconds > 0) { + Thread timeoutThread = new Thread(new Runnable() { + @Override + public void run() { + timeoutThread(); + } + }); + + timeoutThread.setDaemon(true); + timeoutThread.start(); + } serving = true; if (port == 0) { diff --git a/src/main/java/com/google/devtools/build/lib/server/RPCServer.java b/src/main/java/com/google/devtools/build/lib/server/RPCServer.java index 1997498209..8e71477b49 100644 --- a/src/main/java/com/google/devtools/build/lib/server/RPCServer.java +++ b/src/main/java/com/google/devtools/build/lib/server/RPCServer.java @@ -34,8 +34,8 @@ public abstract class RPCServer { * Present so that we don't need to invoke a constructor with multiple arguments by reflection. */ public interface Factory { - RPCServer create(CommandExecutor commandExecutor, Clock clock, int port, Path serverDirectory) - throws IOException; + RPCServer create(CommandExecutor commandExecutor, Clock clock, int port, Path serverDirectory, + int maxIdleSeconds) throws IOException; } protected RPCServer(Path serverDirectory) throws IOException { |