commit
8b9991fcc7
|
@ -125,6 +125,9 @@ class SpringApplicationShutdownHook implements Runnable {
|
||||||
* @param context the context to clean
|
* @param context the context to clean
|
||||||
*/
|
*/
|
||||||
private void closeAndWait(ConfigurableApplicationContext context) {
|
private void closeAndWait(ConfigurableApplicationContext context) {
|
||||||
|
if (!context.isActive()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
context.close();
|
context.close();
|
||||||
try {
|
try {
|
||||||
int waited = 0;
|
int waited = 0;
|
||||||
|
|
|
@ -26,10 +26,12 @@ import java.util.concurrent.CountDownLatch;
|
||||||
import org.awaitility.Awaitility;
|
import org.awaitility.Awaitility;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.support.AbstractApplicationContext;
|
import org.springframework.context.support.AbstractApplicationContext;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||||
|
@ -91,6 +93,15 @@ class SpringApplicationShutdownHookTests {
|
||||||
assertThat(finished).containsExactly(context, handlerAction);
|
assertThat(finished).containsExactly(context, handlerAction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void runDueToExitDuringRefreshWhenContextHasBeenClosedDoesNotDeadlock() throws InterruptedException {
|
||||||
|
GenericApplicationContext context = new GenericApplicationContext();
|
||||||
|
TestSpringApplicationShutdownHook shutdownHook = new TestSpringApplicationShutdownHook();
|
||||||
|
shutdownHook.registerApplicationContext(context);
|
||||||
|
context.registerBean(CloseContextAndExit.class, context, shutdownHook);
|
||||||
|
context.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void runWhenContextIsClosedDirectlyRunsHandlerActions() {
|
void runWhenContextIsClosedDirectlyRunsHandlerActions() {
|
||||||
TestSpringApplicationShutdownHook shutdownHook = new TestSpringApplicationShutdownHook();
|
TestSpringApplicationShutdownHook shutdownHook = new TestSpringApplicationShutdownHook();
|
||||||
|
@ -221,4 +232,28 @@ class SpringApplicationShutdownHookTests {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class CloseContextAndExit implements InitializingBean {
|
||||||
|
|
||||||
|
private final ConfigurableApplicationContext context;
|
||||||
|
|
||||||
|
private final Runnable shutdownHook;
|
||||||
|
|
||||||
|
CloseContextAndExit(ConfigurableApplicationContext context, SpringApplicationShutdownHook shutdownHook) {
|
||||||
|
this.context = context;
|
||||||
|
this.shutdownHook = shutdownHook;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() throws Exception {
|
||||||
|
this.context.close();
|
||||||
|
// Simulate System.exit by running the hook on a separate thread and waiting
|
||||||
|
// for it to complete
|
||||||
|
Thread thread = new Thread(this.shutdownHook);
|
||||||
|
thread.start();
|
||||||
|
thread.join(15000);
|
||||||
|
assertThat(thread.isAlive()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue