]> nmode's Git Repositories - signal-cli/blob - src/main/java/org/asamk/signal/Shutdown.java
Extend shutdown request with optional error
[signal-cli] / src / main / java / org / asamk / signal / Shutdown.java
1 package org.asamk.signal;
2
3 import org.asamk.signal.commands.exceptions.CommandException;
4 import org.slf4j.Logger;
5 import org.slf4j.LoggerFactory;
6
7 import java.util.concurrent.CompletableFuture;
8 import java.util.concurrent.ExecutionException;
9
10 import sun.misc.Signal;
11
12 public class Shutdown {
13
14 private static final Logger logger = LoggerFactory.getLogger(Shutdown.class);
15 private static final CompletableFuture<Object> shutdown = new CompletableFuture<>();
16 private static final CompletableFuture<Void> shutdownComplete = new CompletableFuture<>();
17 private static boolean initialized = false;
18
19 public static void installHandler() {
20 if (initialized) {
21 return;
22 }
23 initialized = true;
24 Signal.handle(new Signal("INT"), Shutdown::handleSignal);
25 Signal.handle(new Signal("TERM"), Shutdown::handleSignal);
26 Runtime.getRuntime().addShutdownHook(Thread.ofPlatform().unstarted(() -> {
27 logger.debug("JVM is shutting down");
28 if (!shutdown.isDone()) {
29 triggerShutdown();
30 }
31
32 try {
33 logger.debug("Waiting for app to shut down");
34 shutdownComplete.get();
35 logger.debug("Exiting");
36 } catch (InterruptedException | ExecutionException e) {
37 throw new RuntimeException(e);
38 }
39 }));
40 }
41
42 public static void triggerShutdown() {
43 logger.debug("Triggering shutdown.");
44 shutdown.complete(null);
45 }
46
47 public static void triggerShutdown(CommandException exception) {
48 logger.debug("Triggering shutdown with exception.", exception);
49 shutdown.complete(exception);
50 }
51
52 public static void waitForShutdown() throws InterruptedException, CommandException {
53 try {
54 final var result = shutdown.get();
55 if (result instanceof CommandException e) {
56 throw e;
57 }
58 } catch (ExecutionException e) {
59 throw new RuntimeException(e);
60 }
61 }
62
63 public static void registerShutdownListener(Runnable action) {
64 shutdown.thenRun(action);
65 }
66
67 static void shutdownComplete() {
68 shutdownComplete.complete(null);
69 }
70
71 private static void handleSignal(Signal signal) {
72 logger.info("Received {} signal, shutting down ...", signal);
73 triggerShutdown();
74 }
75 }