]> nmode's Git Repositories - signal-cli/commitdiff
Add infrastructure for better shutdown handling
authorAsamK <asamk@gmx.de>
Thu, 9 Nov 2023 15:01:08 +0000 (16:01 +0100)
committerAsamK <asamk@gmx.de>
Thu, 9 Nov 2023 18:23:11 +0000 (19:23 +0100)
src/main/java/org/asamk/signal/Main.java
src/main/java/org/asamk/signal/Shutdown.java [new file with mode: 0644]

index b8973bec1f3e4b0cda45c79c48c79e19154a4f7f..9219a1d6e7a04c08b781c8faaa38d57b4804dfb8 100644 (file)
@@ -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 (file)
index 0000000..a59497c
--- /dev/null
@@ -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<Void> shutdown = new CompletableFuture<>();
+    private static final CompletableFuture<Void> 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();
+    }
+}