1 package org
.asamk
.signal
;
3 import org
.asamk
.signal
.commands
.exceptions
.CommandException
;
4 import org
.slf4j
.Logger
;
5 import org
.slf4j
.LoggerFactory
;
7 import java
.util
.concurrent
.CompletableFuture
;
8 import java
.util
.concurrent
.ExecutionException
;
10 import sun
.misc
.Signal
;
12 public class Shutdown
{
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;
19 public static void installHandler() {
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()) {
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
);
42 public static void triggerShutdown() {
43 logger
.debug("Triggering shutdown.");
44 shutdown
.complete(null);
47 public static void triggerShutdown(CommandException exception
) {
48 logger
.debug("Triggering shutdown with exception.", exception
);
49 shutdown
.complete(exception
);
52 public static void waitForShutdown() throws InterruptedException
, CommandException
{
54 final var result
= shutdown
.get();
55 if (result
instanceof CommandException e
) {
58 } catch (ExecutionException e
) {
59 throw new RuntimeException(e
);
63 public static void registerShutdownListener(Runnable action
) {
64 shutdown
.thenRun(action
);
67 static void shutdownComplete() {
68 shutdownComplete
.complete(null);
71 private static void handleSignal(Signal signal
) {
72 logger
.info("Received {} signal, shutting down ...", signal
);