From c5b5b1e1c04a2f5c67e40197ebd68ca3b4524b67 Mon Sep 17 00:00:00 2001 From: Gavin Williams Date: Wed, 13 Oct 2021 22:32:36 +0100 Subject: [PATCH] Add TERM handling This is useful to gracefully stop the Jenkins swarm process, for example when running in Kubernetes in conjunction with a preStop lifecycle hook. Signed-off-by: Gavin Williams --- .../java/hudson/plugins/swarm/Client.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/client/src/main/java/hudson/plugins/swarm/Client.java b/client/src/main/java/hudson/plugins/swarm/Client.java index 539dea25..1dd7be56 100644 --- a/client/src/main/java/hudson/plugins/swarm/Client.java +++ b/client/src/main/java/hudson/plugins/swarm/Client.java @@ -24,6 +24,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; +import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -187,6 +188,34 @@ private static void validateOptions(Options options) { */ static void run(SwarmClient swarmClient, Options options, String... args) throws InterruptedException { + + // Gracefully handle TERM request + Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + logger.info("Interrupting threads"); + Set runningThreads = Thread.getAllStackTraces().keySet(); + for (Thread th : runningThreads) { + if (th != Thread.currentThread() && !th.isDaemon() + && th.getClass().getName().startsWith("hudson.plugins.swarm")) { + logger.info("Interrupting '" + th.getClass() + "' termination"); + th.interrupt(); + } + } + for (Thread th : runningThreads) { + try { + if (th != Thread.currentThread() && !th.isDaemon() && th.isInterrupted()) { + logger.info("Waiting '" + th.getName() + "' termination"); + th.join(); + } + } catch (InterruptedException ex) { + logger.info("Shutdown interrupted"); + } + } + logger.info("Shutdown finished"); + } + }); + logger.info("Connecting to Jenkins controller"); URL url = swarmClient.getUrl();