Repository: quarkusio/quarkus
Issue: dev mode doesn't recover when an invalid value (typo, space) is added to logging level configuration

Dev mode doesn't recover when an invalid value (typo, space) is added to logging level configuration
When the value is corrected, Quarkus still isn't able to restart itself.

Reproducer:
```
mvn io.quarkus:quarkus-maven-plugin:1.3.2.Final:create \\
    -DprojectGroupId=org.acme \\
    -DprojectArtifactId=getting-started \\
    -DclassName="org.acme.getting.started.GreetingResource" \\
    -Dpath="/hello"
cd getting-started
mvn quarkus:dev

open src/main/resources/application.properties
add 'quarkus.log.category."org.hibernate".level=DEBUG ' (extra space at the end) into application.properties
open http://localhost:8080/hello
remove extra space at the end of quarkus.log.category line in application.properties
open http://localhost:8080/hello
```

Log reports:
```
2020-04-10 22:16:26,799 INFO  [io.qua.dev] (vert.x-worker-thread-2) File change detected: /Users/rsvoboda/Downloads/ffff/getting-started/src/main/resources/application.properties
2020-04-10 22:16:26,824 INFO  [io.quarkus] (vert.x-worker-thread-2) Quarkus stopped in 0.021s
```

Stacktrace from http://localhost:8080/hello
```
io.quarkus.runtime.configuration.ConfigurationException: One or more configuration errors has prevented the application from starting. The errors are:
An invalid value was given for configuration key "quarkus.log.category."org.hibernate".level": java.lang.reflect.InvocationTargetException
Resulted in: java.lang.RuntimeException: Failed to start quarkus
	at io.quarkus.runner.ApplicationImpl.doStart(ApplicationImpl.zig:232)
	at io.quarkus.runtime.Application.start(Application.java:90)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at io.quarkus.runner.bootstrap.StartupActionImpl.run(StartupActionImpl.java:99)
	at io.quarkus.dev.IsolatedDevModeMain.restartApp(IsolatedDevModeMain.java:103)
	at io.quarkus.dev.RuntimeUpdatesProcessor.doScan(RuntimeUpdatesProcessor.java:138)
	at io.quarkus.vertx.http.runtime.devmode.VertxHotReplacementSetup$1.handle(VertxHotReplacementSetup.java:50)
	at io.quarkus.vertx.http.runtime.devmode.VertxHotReplacementSetup$1.handle(VertxHotReplacementSetup.java:42)
	at io.vertx.core.impl.ContextImpl.lambda$executeBlocking$2(ContextImpl.java:316)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:834)
```


Changed files:
core/runtime/src/main/java/io/quarkus/runtime/Application.java
core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java
core/deployment/src/main/java/io/quarkus/deployment/dev/IsolatedDevModeMain.java
core/runtime/src/main/java/io/quarkus/runtime/ApplicationLifecycleManager.java

diff --git a/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java b/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java
index 75701f2430b..f14e9627fb4 100644
--- a/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java
+++ b/core/deployment/src/main/java/io/quarkus/deployment/configuration/RunTimeConfigurationGenerator.java
@@ -687,7 +687,7 @@ public void run() {
             ResultHandle niceErrorMessage = isError
                     .invokeStaticMethod(
                             MethodDescriptor.ofMethod(ConfigDiagnostic.class, "getNiceErrorMessage", String.class));
-            readConfig.invokeStaticMethod(CD_RESET_ERROR);
+            isError.invokeStaticMethod(CD_RESET_ERROR);
 
             // throw the proper exception
             final ResultHandle finalErrorMessageBuilder = isError.newInstance(SB_NEW);
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 7de869ce931..a274fd09848 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
@@ -119,7 +119,6 @@ public void accept(Integer integer) {
     public synchronized void restartApp(Set<String> changedResources) {
         restarting = true;
         stop();
-        restarting = false;
         Timing.restart(curatedApplication.getAugmentClassLoader());
         deploymentProblem = null;
         ClassLoader old = Thread.currentThread().getContextClassLoader();
@@ -134,6 +133,7 @@ public synchronized void restartApp(Set<String> changedResources) {
                 log.error("Failed to start quarkus", t);
             }
         } finally {
+            restarting = false;
             Thread.currentThread().setContextClassLoader(old);
         }
     }
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 c6b2fb59bd2..47be7673547 100644
--- a/core/runtime/src/main/java/io/quarkus/runtime/Application.java
+++ b/core/runtime/src/main/java/io/quarkus/runtime/Application.java
@@ -5,6 +5,7 @@
 import java.util.concurrent.locks.Lock;
 
 import org.eclipse.microprofile.config.spi.ConfigProviderResolver;
+import org.jboss.logging.Logger;
 import org.wildfly.common.Assert;
 import org.wildfly.common.lock.Locks;
 
@@ -88,6 +89,12 @@ public final void start(String[] args) {
             doStart(args);
         } catch (Throwable t) {
             stateLock.lock();
+            final ConfigProviderResolver cpr = ConfigProviderResolver.instance();
+            try {
+                cpr.releaseConfig(cpr.getConfig());
+            } catch (IllegalStateException ignored) {
+                // just means no config was installed, which is fine
+            }
             try {
                 state = ST_STOPPED;
                 stateCond.signalAll();
@@ -129,6 +136,15 @@ public final void close() {
      * stop, that exception is propagated.
      */
     public final void stop() {
+        stop(null);
+    }
+
+    /**
+     * Stop the application. If another thread is also trying to stop the application, this method waits for that
+     * thread to finish. Returns immediately if the application is already stopped. If an exception is thrown during
+     * stop, that exception is propagated.
+     */
+    public final void stop(Runnable afterStopTask) {
         final Lock stateLock = this.stateLock;
         stateLock.lock();
         try {
@@ -171,6 +187,13 @@ public final void stop() {
             doStop();
         } finally {
             currentApplication = null;
+            if (afterStopTask != null) {
+                try {
+                    afterStopTask.run();
+                } catch (Throwable t) {
+                    Logger.getLogger(Application.class).error("Failed to run stop task", t);
+                }
+            }
             stateLock.lock();
             try {
                 state = ST_STOPPED;
diff --git a/core/runtime/src/main/java/io/quarkus/runtime/ApplicationLifecycleManager.java b/core/runtime/src/main/java/io/quarkus/runtime/ApplicationLifecycleManager.java
index 9827cf7e698..629062c9a12 100644
--- a/core/runtime/src/main/java/io/quarkus/runtime/ApplicationLifecycleManager.java
+++ b/core/runtime/src/main/java/io/quarkus/runtime/ApplicationLifecycleManager.java
@@ -142,8 +142,12 @@ public static final void run(Application application, Class<? extends QuarkusApp
             } finally {
                 stateLock.unlock();
             }
-            application.stop();
-            (exitCodeHandler == null ? defaultExitCodeHandler : exitCodeHandler).accept(1);
+            application.stop(new Runnable() {
+                @Override
+                public void run() {
+                    (exitCodeHandler == null ? defaultExitCodeHandler : exitCodeHandler).accept(1);
+                }
+            });
             return;
         }
         if (!alreadyStarted) {