From f941994bd32aa6b7d6a2899885e6f5680d4fbf57 Mon Sep 17 00:00:00 2001 From: Stuart Douglas Date: Tue, 31 Mar 2020 16:15:15 +1100 Subject: [PATCH] Fix issue with application state notification --- .../deployment/dev/IsolatedDevModeMain.java | 5 --- .../runner/bootstrap/StartupActionImpl.java | 6 ++-- .../ApplicationStateNotification.java | 34 ++++++++++++++----- .../java/io/quarkus/runtime/Application.java | 4 +-- 4 files changed, 32 insertions(+), 17 deletions(-) diff --git a/core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java b/core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java index ad76df0e384f4..6c274086c43bb 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java @@ -29,7 +29,6 @@ import io.quarkus.builder.BuildContext; import io.quarkus.builder.BuildStep; import io.quarkus.deployment.builditem.ApplicationClassPredicateBuildItem; -import io.quarkus.dev.appstate.ApplicationStateNotification; import io.quarkus.dev.spi.HotReplacementSetup; import io.quarkus.runner.bootstrap.AugmentActionImpl; import io.quarkus.runtime.ApplicationLifecycleManager; @@ -120,9 +119,6 @@ public void accept(Integer integer) { public synchronized void restartApp(Set changedResources) { restarting = true; stop(); - - //this clears any old state - ApplicationStateNotification.notifyApplicationStopped(); restarting = false; Timing.restart(curatedApplication.getAugmentClassLoader()); deploymentProblem = null; @@ -133,7 +129,6 @@ public synchronized void restartApp(Set changedResources) { try { StartupAction start = augmentAction.reloadExistingApplication(changedResources); runner = start.runMainClass(); - ApplicationStateNotification.waitForApplicationStart(); } catch (Throwable t) { deploymentProblem = t; log.error("Failed to start quarkus", t); diff --git a/core/deployment/src/main/java/io/quarkus/runner/bootstrap/StartupActionImpl.java b/core/deployment/src/main/java/io/quarkus/runner/bootstrap/StartupActionImpl.java index de3a34cacec18..bce61a19147e1 100644 --- a/core/deployment/src/main/java/io/quarkus/runner/bootstrap/StartupActionImpl.java +++ b/core/deployment/src/main/java/io/quarkus/runner/bootstrap/StartupActionImpl.java @@ -78,9 +78,12 @@ public StartupActionImpl(CuratedApplication curatedApplication, BuildResult buil * of the JVM will exit when the app stops. */ public RunningQuarkusApplication runMainClass(String... args) throws Exception { - //first + + //first we hack around class loading in the fork join pool ForkJoinClassLoading.setForkJoinClassLoader(runtimeClassLoader); + //this clears any old state, and gets ready to start again + ApplicationStateNotification.reset(); //we have our class loaders ClassLoader old = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(runtimeClassLoader); @@ -97,7 +100,6 @@ public void run() { start.invoke(null, (Object) args); } catch (Throwable e) { log.error("Error running Quarkus", e); - ApplicationStateNotification.notifyStartupComplete(e.getCause()); } } }, "Quarkus Main Thread"); diff --git a/core/devmode-spi/src/main/java/io/quarkus/dev/appstate/ApplicationStateNotification.java b/core/devmode-spi/src/main/java/io/quarkus/dev/appstate/ApplicationStateNotification.java index d5c4d38baa86d..a54c442b2961d 100644 --- a/core/devmode-spi/src/main/java/io/quarkus/dev/appstate/ApplicationStateNotification.java +++ b/core/devmode-spi/src/main/java/io/quarkus/dev/appstate/ApplicationStateNotification.java @@ -12,23 +12,35 @@ */ public class ApplicationStateNotification { - private static boolean started = false; + private static State state = State.INITIAL; private static Throwable startupProblem; - public static synchronized void notifyStartupComplete(Throwable sp) { - started = startupProblem == null; - startupProblem = sp; + public static synchronized void reset() { + if (state == State.STARTED) { + throw new IllegalStateException("Cannot reset a started application"); + } + state = State.INITIAL; + startupProblem = null; + } + + public static synchronized void notifyStartupComplete() { + state = State.STARTED; ApplicationStateNotification.class.notifyAll(); } public static synchronized void notifyApplicationStopped() { - started = false; - startupProblem = null; + state = State.STOPPED; + ApplicationStateNotification.class.notifyAll(); + } + + public static synchronized void notifyStartupFailed(Throwable t) { + startupProblem = t; + state = State.STOPPED; ApplicationStateNotification.class.notifyAll(); } public static synchronized void waitForApplicationStart() { - while (!started && startupProblem == null) { + while (state == State.INITIAL) { try { ApplicationStateNotification.class.wait(); } catch (InterruptedException e) { @@ -41,7 +53,7 @@ public static synchronized void waitForApplicationStart() { } public static synchronized void waitForApplicationStop() { - while (started) { + while (state != State.STOPPED) { try { ApplicationStateNotification.class.wait(); } catch (InterruptedException e) { @@ -49,4 +61,10 @@ public static synchronized void waitForApplicationStop() { } } } + + enum State { + INITIAL, + STARTED, + STOPPED + } } diff --git a/core/runtime/src/main/java/io/quarkus/runtime/Application.java b/core/runtime/src/main/java/io/quarkus/runtime/Application.java index 73547954da406..c6b2fb59bd2d7 100644 --- a/core/runtime/src/main/java/io/quarkus/runtime/Application.java +++ b/core/runtime/src/main/java/io/quarkus/runtime/Application.java @@ -94,14 +94,14 @@ public final void start(String[] args) { } finally { stateLock.unlock(); } - ApplicationStateNotification.notifyStartupComplete(t); + ApplicationStateNotification.notifyStartupFailed(t); throw t; } stateLock.lock(); try { state = ST_STARTED; stateCond.signalAll(); - ApplicationStateNotification.notifyStartupComplete(null); + ApplicationStateNotification.notifyStartupComplete(); } finally { stateLock.unlock(); }