Skip to content

Commit 5d741e1

Browse files
committed
Catch Throwable in ApplicationLifecycleManager
This is needed because we need to always perform the proper shutdown sequence, not just for regular Exception classes
1 parent 97cebb8 commit 5d741e1

File tree

3 files changed

+54
-4
lines changed

3 files changed

+54
-4
lines changed

core/runtime/src/main/java/io/quarkus/runtime/ApplicationLifecycleManager.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,8 @@ public static void run(Application application, Class<? extends QuarkusApplicati
164164
stateLock.unlock();
165165
}
166166
}
167-
} catch (Exception e) {
168-
Throwable rootCause = ExceptionUtil.getRootCause(e);
167+
} catch (Throwable t) {
168+
Throwable rootCause = ExceptionUtil.getRootCause(t);
169169
if (exitCodeHandler == null) {
170170
Logger applicationLogger = Logger.getLogger(Application.class);
171171
if (rootCause instanceof QuarkusBindException qbe) {
@@ -198,7 +198,7 @@ public static void run(Application application, Class<? extends QuarkusApplicati
198198
&& !StringUtil.isNullOrEmpty(rootCause.getMessage())) {
199199
System.err.println(rootCause.getMessage());
200200
} else {
201-
applicationLogger.errorv(e, "Failed to start application");
201+
applicationLogger.errorv(t, "Failed to start application");
202202
ensureConsoleLogsDrained();
203203
}
204204
}
@@ -214,7 +214,7 @@ public static void run(Application application, Class<? extends QuarkusApplicati
214214
? ((PreventFurtherStepsException) rootCause).getExitCode()
215215
: 1;
216216
currentApplication = null;
217-
(exitCodeHandler == null ? defaultExitCodeHandler : exitCodeHandler).accept(exceptionExitCode, e);
217+
(exitCodeHandler == null ? defaultExitCodeHandler : exitCodeHandler).accept(exceptionExitCode, t);
218218
return;
219219
} finally {
220220
try {
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package io.quarkus.it.testsupport.commandmode;
2+
3+
import io.quarkus.runtime.QuarkusApplication;
4+
import io.quarkus.runtime.annotations.QuarkusMain;
5+
6+
/*
7+
* Because this app co-exists in a module with a QuarkusIntegrationTest, it needs to not be on the default path.
8+
* Otherwise, this application is executed by the QuarkusIntegrationTest and exits early, causing test failures elsewhere.
9+
*/
10+
@QuarkusMain(name = "failing-application")
11+
public class FailingApp implements QuarkusApplication {
12+
13+
@Override
14+
public int run(String... args) throws Exception {
15+
// the point of this is to verify that Quarkus can properly shut down in the face of an Error (not an Exception)
16+
throw new NoSuchMethodError("dummy");
17+
}
18+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package io.quarkus.it.testsupport.commandmode;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import java.util.Map;
6+
7+
import org.junit.jupiter.api.Test;
8+
9+
import io.quarkus.test.junit.QuarkusTestProfile;
10+
import io.quarkus.test.junit.TestProfile;
11+
import io.quarkus.test.junit.main.Launch;
12+
import io.quarkus.test.junit.main.LaunchResult;
13+
import io.quarkus.test.junit.main.QuarkusMainTest;
14+
15+
@QuarkusMainTest
16+
@TestProfile(QuarkusMainTestWithTestProfileAndFailingApplicationTestCase.MyTestProfile.class)
17+
public class QuarkusMainTestWithTestProfileAndFailingApplicationTestCase {
18+
19+
@Test
20+
@Launch(value = {}, exitCode = 1)
21+
public void testLaunchCommand(LaunchResult result) {
22+
assertThat(result.getOutput()).contains("dummy");
23+
}
24+
25+
public static class MyTestProfile implements QuarkusTestProfile {
26+
27+
@Override
28+
public Map<String, String> getConfigOverrides() {
29+
return Map.of("quarkus.package.main-class", "failing-application");
30+
}
31+
}
32+
}

0 commit comments

Comments
 (0)