diff --git a/common/src/main/java/bisq/common/setup/CommonSetup.java b/common/src/main/java/bisq/common/setup/CommonSetup.java index df3280aae7f..f2fac170fce 100644 --- a/common/src/main/java/bisq/common/setup/CommonSetup.java +++ b/common/src/main/java/bisq/common/setup/CommonSetup.java @@ -102,13 +102,13 @@ protected static void setSystemProperties() { protected static void setupSigIntHandlers(GracefulShutDownHandler gracefulShutDownHandler) { Signal.handle(new Signal("INT"), signal -> { - gracefulShutDownHandler.gracefulShutDown(() -> { - }); + UserThread.execute(() -> gracefulShutDownHandler.gracefulShutDown(() -> { + })); }); Signal.handle(new Signal("TERM"), signal -> { - gracefulShutDownHandler.gracefulShutDown(() -> { - }); + UserThread.execute(() -> gracefulShutDownHandler.gracefulShutDown(() -> { + })); }); } diff --git a/core/src/main/java/bisq/core/app/BisqSetup.java b/core/src/main/java/bisq/core/app/BisqSetup.java index 3660544f60d..0f608b1a99e 100644 --- a/core/src/main/java/bisq/core/app/BisqSetup.java +++ b/core/src/main/java/bisq/core/app/BisqSetup.java @@ -260,7 +260,6 @@ public void start() { } private void step2() { - torSetup.cleanupTorFiles(); readMapsFromResources(this::step3); checkForCorrectOSArchitecture(); checkOSXVersion(); diff --git a/core/src/main/java/bisq/core/app/TorSetup.java b/core/src/main/java/bisq/core/app/TorSetup.java index b2ff5378b79..b855e514622 100644 --- a/core/src/main/java/bisq/core/app/TorSetup.java +++ b/core/src/main/java/bisq/core/app/TorSetup.java @@ -46,15 +46,7 @@ public TorSetup(@Named(Config.TOR_DIR) File torDir) { this.torDir = checkDir(torDir); } - public void cleanupTorFiles() { - cleanupTorFiles(null, null); - } - - // We get sometimes Tor startup problems which is related to some tor files in the tor directory. It happens - // more often if the application got killed (not graceful shutdown). - // Creating all tor files newly takes about 3-4 sec. longer and it does not benefit from cache files. - // TODO: We should fix those startup problems in the netlayer library, once fixed there we can remove that call at the - // Bisq startup again. + // Should only be called if needed. Slows down Tor startup from about 5 sec. to 30 sec. if it gets deleted. public void cleanupTorFiles(@Nullable Runnable resultHandler, @Nullable ErrorMessageHandler errorMessageHandler) { File hiddenservice = new File(Paths.get(torDir.getAbsolutePath(), "hiddenservice").toString()); try { diff --git a/core/src/main/java/bisq/core/app/misc/AppSetupWithP2P.java b/core/src/main/java/bisq/core/app/misc/AppSetupWithP2P.java index 8b2dc545d6c..bad57eba85a 100644 --- a/core/src/main/java/bisq/core/app/misc/AppSetupWithP2P.java +++ b/core/src/main/java/bisq/core/app/misc/AppSetupWithP2P.java @@ -73,7 +73,6 @@ public AppSetupWithP2P(P2PService p2PService, @Override public void initPersistedDataHosts() { - torSetup.cleanupTorFiles(); persistedDataHosts.add(p2PService); // we apply at startup the reading of persisted data but don't want to get it triggered in the constructor diff --git a/p2p/src/main/java/bisq/network/p2p/network/TorNetworkNode.java b/p2p/src/main/java/bisq/network/p2p/network/TorNetworkNode.java index c7d0b9e028b..a1aae19babc 100644 --- a/p2p/src/main/java/bisq/network/p2p/network/TorNetworkNode.java +++ b/p2p/src/main/java/bisq/network/p2p/network/TorNetworkNode.java @@ -23,7 +23,6 @@ import bisq.common.Timer; import bisq.common.UserThread; import bisq.common.proto.network.NetworkProtoResolver; -import bisq.common.util.Utilities; import org.berndpruenster.netlayer.tor.HiddenServiceSocket; import org.berndpruenster.netlayer.tor.Tor; @@ -82,13 +81,14 @@ public class TorNetworkNode extends NetworkNode { private boolean streamIsolation; private Socks5Proxy socksProxy; + private ListenableFuture torStartupFuture; /////////////////////////////////////////////////////////////////////////////////////////// // Constructor /////////////////////////////////////////////////////////////////////////////////////////// public TorNetworkNode(int servicePort, NetworkProtoResolver networkProtoResolver, boolean useStreamIsolation, - TorMode torMode) { + TorMode torMode) { super(servicePort, networkProtoResolver); this.torMode = torMode; this.streamIsolation = useStreamIsolation; @@ -153,72 +153,60 @@ public void shutDown(@Nullable Runnable shutDownCompleteHandler) { // this one is committed as a thread to the executor BooleanProperty torNetworkNodeShutDown = torNetworkNodeShutDown(); BooleanProperty shutDownTimerTriggered = shutDownTimerTriggered(); - // Need to store allShutDown to not get garbage collected - allShutDown = EasyBind.combine(torNetworkNodeShutDown, networkNodeShutDown, shutDownTimerTriggered, (a, b, c) -> (a && b) || c); + allShutDown = EasyBind.combine(torNetworkNodeShutDown, networkNodeShutDown, shutDownTimerTriggered, + (a, b, c) -> (a && b) || c); allShutDown.subscribe((observable, oldValue, newValue) -> { if (newValue) { shutDownTimeoutTimer.stop(); long ts = System.currentTimeMillis(); - log.debug("Shutdown executorService"); try { MoreExecutors.shutdownAndAwaitTermination(executorService, 500, TimeUnit.MILLISECONDS); - log.debug("Shutdown executorService done after " + (System.currentTimeMillis() - ts) + " ms."); - log.debug("Shutdown completed"); + log.debug("Shutdown executorService done after {} ms.", System.currentTimeMillis() - ts); } catch (Throwable t) { - log.error("Shutdown executorService failed with exception: " + t.getMessage()); + log.error("Shutdown executorService failed with exception: {}", t.getMessage()); t.printStackTrace(); } finally { - try { - if (shutDownCompleteHandler != null) - shutDownCompleteHandler.run(); - } catch (Throwable ignore) { - } + if (shutDownCompleteHandler != null) + shutDownCompleteHandler.run(); } } }); } private BooleanProperty torNetworkNodeShutDown() { - final BooleanProperty done = new SimpleBooleanProperty(); - if (executorService != null) { - executorService.submit(() -> { - Utilities.setThreadName("torNetworkNodeShutDown"); - long ts = System.currentTimeMillis(); - log.debug("Shutdown torNetworkNode"); - try { - /** - * make sure we get tor. - * - there have been situations where tor isn't set yet, which would leave tor running - * - downside is that if tor is not already started, we start it here just to shut it down. However, - * that can only be the case if Bisq gets shutdown even before it reaches step 2/4 at startup. - * The risk seems worth it compared to the risk of not shutting down tor. - */ - tor = Tor.getDefault(); - if (tor != null) - tor.shutdown(); - log.debug("Shutdown torNetworkNode done after " + (System.currentTimeMillis() - ts) + " ms."); - } catch (Throwable e) { - log.error("Shutdown torNetworkNode failed with exception: " + e.getMessage()); - e.printStackTrace(); - } finally { - UserThread.execute(() -> done.set(true)); - } - }); - } else { - done.set(true); + BooleanProperty done = new SimpleBooleanProperty(); + try { + tor = Tor.getDefault(); + if (tor != null) { + log.info("Tor has been created already so we can shut it down."); + tor.shutdown(); + log.info("Tor shut down completed"); + } else { + log.info("Tor has not been created yet. We cancel the torStartupFuture."); + torStartupFuture.cancel(true); + log.info("torStartupFuture cancelled"); + } + } catch (Throwable e) { + log.error("Shutdown torNetworkNode failed with exception: {}", e.getMessage()); + e.printStackTrace(); + + } finally { + // We need to delay as otherwise our listener would not get called if shutdown completes in synchronous manner + UserThread.execute(() -> done.set(true)); } return done; } private BooleanProperty networkNodeShutDown() { - final BooleanProperty done = new SimpleBooleanProperty(); - super.shutDown(() -> done.set(true)); + BooleanProperty done = new SimpleBooleanProperty(); + // We need to delay as otherwise our listener would not get called if shutdown completes in synchronous manner + UserThread.execute(() -> super.shutDown(() -> done.set(true))); return done; } private BooleanProperty shutDownTimerTriggered() { - final BooleanProperty done = new SimpleBooleanProperty(); + BooleanProperty done = new SimpleBooleanProperty(); shutDownTimeoutTimer = UserThread.runAfter(() -> { log.error("A timeout occurred at shutDown"); done.set(true); @@ -255,7 +243,7 @@ private void restartTor(String errorMessage) { /////////////////////////////////////////////////////////////////////////////////////////// private void createTorAndHiddenService(int localPort, int servicePort) { - ListenableFuture future = executorService.submit(() -> { + torStartupFuture = executorService.submit(() -> { try { // get tor Tor.setDefault(torMode.getTor()); @@ -313,7 +301,7 @@ public void run() { return null; }); - Futures.addCallback(future, new FutureCallback() { + Futures.addCallback(torStartupFuture, new FutureCallback() { public void onSuccess(Void ignore) { }