diff --git a/proxy/src/main/java/net/azisaba/simpleproxy/proxy/ProxyInstance.java b/proxy/src/main/java/net/azisaba/simpleproxy/proxy/ProxyInstance.java index c8c01ee..ea75cf5 100644 --- a/proxy/src/main/java/net/azisaba/simpleproxy/proxy/ProxyInstance.java +++ b/proxy/src/main/java/net/azisaba/simpleproxy/proxy/ProxyInstance.java @@ -37,10 +37,7 @@ import java.util.Arrays; import java.util.List; import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicLong; public class ProxyInstance implements ProxyServer { @@ -175,7 +172,12 @@ public void handleCommand(@NotNull String input) { @Override public CompletableFuture reloadConfig() { return CompletableFuture.runAsync(() -> { - closeListeners(); + try { + closeListeners(); + } catch (ExecutionException | InterruptedException | TimeoutException e) { + LOGGER.error(e); + Thread.currentThread().interrupt(); + } LOGGER.info("Loading config"); try { ProxyConfigInstance.init(); @@ -238,17 +240,17 @@ public ProxyConfig getConfig() { return proxyConfig; } - public void closeListeners() { + public void closeListeners() throws ExecutionException, InterruptedException, TimeoutException { if (connectionListener != null) { LOGGER.info("Closing listeners"); - connectionListener.closeFutures(); + connectionListener.closeFutures().get(3, TimeUnit.MINUTES); } } - public void fullyCloseListeners() { + public void fullyCloseListeners() throws ExecutionException, InterruptedException, TimeoutException { if (connectionListener != null) { LOGGER.info("Closing listeners"); - connectionListener.close(); + connectionListener.close().get(3, TimeUnit.MINUTES); connectionListener = null; } } @@ -264,13 +266,14 @@ public void stop() { } catch (IOException e) { LOGGER.warn("Failed to close plugin loader", e); } - fullyCloseListeners(); - LOGGER.info("Shutting down executor"); - worker.shutdownNow(); try { + fullyCloseListeners(); + LOGGER.info("Shutting down executor"); + worker.shutdownNow(); //noinspection ResultOfMethodCallIgnored worker.awaitTermination(3, TimeUnit.MINUTES); - } catch (InterruptedException e) { + } catch (InterruptedException | ExecutionException | TimeoutException e) { + LOGGER.error(e); Thread.currentThread().interrupt(); } LOGGER.info("Goodbye!"); diff --git a/proxy/src/main/java/net/azisaba/simpleproxy/proxy/connection/ConnectionListener.java b/proxy/src/main/java/net/azisaba/simpleproxy/proxy/connection/ConnectionListener.java index f719feb..ae830b4 100644 --- a/proxy/src/main/java/net/azisaba/simpleproxy/proxy/connection/ConnectionListener.java +++ b/proxy/src/main/java/net/azisaba/simpleproxy/proxy/connection/ConnectionListener.java @@ -31,7 +31,10 @@ import java.util.ArrayList; import java.util.List; import java.util.Random; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicLong; public class ConnectionListener { @@ -193,21 +196,29 @@ protected void initChannel(@NotNull Channel ch) { .connect(serverInfo.getHost(), serverInfo.getPort()); } - public void closeFutures() { - for (ChannelFuture future : futures) { - if (future.channel().isActive() || future.channel().isOpen()) { - LOGGER.info("Closing future/listener: {}", future.channel().toString()); - future.channel().close().syncUninterruptibly(); + public @NotNull CompletableFuture closeFutures() { + return CompletableFuture.runAsync(() -> { + for (ChannelFuture future : futures) { + if (future.channel().isActive() || future.channel().isOpen()) { + LOGGER.info("Closing future/listener: {}", future.channel().toString()); + future.channel().close().syncUninterruptibly(); + } } - } - futures.clear(); + futures.clear(); + }); } - public void close() { - closeFutures(); - LOGGER.info("Shutting down event loop"); - clientWorkerGroup.shutdownGracefully().syncUninterruptibly(); - workerGroup.shutdownGracefully().syncUninterruptibly(); - bossGroup.shutdownGracefully().syncUninterruptibly(); + public @NotNull CompletableFuture close() { + return CompletableFuture.runAsync(() -> { + try { + closeFutures().get(3, TimeUnit.MINUTES); + } catch (InterruptedException | TimeoutException | ExecutionException e) { + LOGGER.error(e); + } + LOGGER.info("Shutting down event loop"); + clientWorkerGroup.shutdownGracefully().syncUninterruptibly(); + workerGroup.shutdownGracefully().syncUninterruptibly(); + bossGroup.shutdownGracefully().syncUninterruptibly(); + }); } }