|
26 | 26 | import org.awaitility.Awaitility;
|
27 | 27 | import org.junit.jupiter.api.Test;
|
28 | 28 |
|
| 29 | +import org.springframework.beans.factory.InitializingBean; |
29 | 30 | import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
30 | 31 | import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
31 | 32 | import org.springframework.context.ConfigurableApplicationContext;
|
32 | 33 | import org.springframework.context.support.AbstractApplicationContext;
|
| 34 | +import org.springframework.context.support.GenericApplicationContext; |
33 | 35 |
|
34 | 36 | import static org.assertj.core.api.Assertions.assertThat;
|
35 | 37 | import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
@@ -91,6 +93,15 @@ void runWhenContextIsBeingClosedInAnotherThreadWaitsUntilContextIsInactive() thr
|
91 | 93 | assertThat(finished).containsExactly(context, handlerAction);
|
92 | 94 | }
|
93 | 95 |
|
| 96 | + @Test |
| 97 | + void runDueToExitDuringRefreshWhenContextHasBeenClosedDoesNotDeadlock() throws InterruptedException { |
| 98 | + GenericApplicationContext context = new GenericApplicationContext(); |
| 99 | + TestSpringApplicationShutdownHook shutdownHook = new TestSpringApplicationShutdownHook(); |
| 100 | + shutdownHook.registerApplicationContext(context); |
| 101 | + context.registerBean(CloseContextAndExit.class, context, shutdownHook); |
| 102 | + context.refresh(); |
| 103 | + } |
| 104 | + |
94 | 105 | @Test
|
95 | 106 | void runWhenContextIsClosedDirectlyRunsHandlerActions() {
|
96 | 107 | TestSpringApplicationShutdownHook shutdownHook = new TestSpringApplicationShutdownHook();
|
@@ -221,4 +232,28 @@ public void run() {
|
221 | 232 |
|
222 | 233 | }
|
223 | 234 |
|
| 235 | + static class CloseContextAndExit implements InitializingBean { |
| 236 | + |
| 237 | + private final ConfigurableApplicationContext context; |
| 238 | + |
| 239 | + private final Runnable shutdownHook; |
| 240 | + |
| 241 | + CloseContextAndExit(ConfigurableApplicationContext context, SpringApplicationShutdownHook shutdownHook) { |
| 242 | + this.context = context; |
| 243 | + this.shutdownHook = shutdownHook; |
| 244 | + } |
| 245 | + |
| 246 | + @Override |
| 247 | + public void afterPropertiesSet() throws Exception { |
| 248 | + this.context.close(); |
| 249 | + // Simulate System.exit by running the hook on a separate thread and waiting |
| 250 | + // for it to complete |
| 251 | + Thread thread = new Thread(this.shutdownHook); |
| 252 | + thread.start(); |
| 253 | + thread.join(15000); |
| 254 | + assertThat(thread.isAlive()).isFalse(); |
| 255 | + } |
| 256 | + |
| 257 | + } |
| 258 | + |
224 | 259 | }
|
0 commit comments