From: AsamK Date: Thu, 9 Nov 2023 15:01:08 +0000 (+0100) Subject: Add infrastructure for better shutdown handling X-Git-Tag: v0.13.0~101 X-Git-Url: https://git.nmode.ca/signal-cli/commitdiff_plain/f252597002c3c95e8ed68338c53a41d519b24dcd?ds=inline Add infrastructure for better shutdown handling --- diff --git a/src/main/java/org/asamk/signal/Main.java b/src/main/java/org/asamk/signal/Main.java index b8973bec..9219a1d6 100644 --- a/src/main/java/org/asamk/signal/Main.java +++ b/src/main/java/org/asamk/signal/Main.java @@ -64,6 +64,7 @@ public class Main { e.printStackTrace(System.err); status = 2; } + Shutdown.shutdownComplete(); System.exit(status); } diff --git a/src/main/java/org/asamk/signal/Shutdown.java b/src/main/java/org/asamk/signal/Shutdown.java new file mode 100644 index 00000000..a59497c9 --- /dev/null +++ b/src/main/java/org/asamk/signal/Shutdown.java @@ -0,0 +1,66 @@ +package org.asamk.signal; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; + +import sun.misc.Signal; + +public class Shutdown { + + private static final Logger logger = LoggerFactory.getLogger(Shutdown.class); + private static final CompletableFuture shutdown = new CompletableFuture<>(); + private static final CompletableFuture shutdownComplete = new CompletableFuture<>(); + private static boolean initialized = false; + + public static void installHandler() { + if (initialized) { + return; + } + initialized = true; + Signal.handle(new Signal("INT"), Shutdown::handleSignal); + Signal.handle(new Signal("TERM"), Shutdown::handleSignal); + Runtime.getRuntime().addShutdownHook(Thread.ofPlatform().unstarted(() -> { + logger.debug("JVM is shutting down"); + if (!shutdown.isDone()) { + triggerShutdown(); + } + + try { + logger.debug("Waiting for app to shut down"); + shutdownComplete.get(); + logger.debug("Exiting"); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + })); + } + + public static void triggerShutdown() { + logger.debug("Triggering shutdown."); + shutdown.complete(null); + } + + public static void waitForShutdown() throws InterruptedException { + try { + shutdown.get(); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + } + + public static void registerShutdownListener(Runnable action) { + shutdown.thenRun(action); + } + + static void shutdownComplete() { + shutdownComplete.complete(null); + } + + private static void handleSignal(Signal signal) { + logger.info("Received {} signal, shutting down ...", signal); + triggerShutdown(); + } +}