Skip to content

Commit b6e860b

Browse files
committed
Prevent Jetty from delaying shutdown beyond grace period
Fixes gh-22689
1 parent 2a89b11 commit b6e860b

File tree

4 files changed

+53
-2
lines changed

4 files changed

+53
-2
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyReactiveWebServerFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -169,6 +169,7 @@ protected Server createJettyServer(JettyHttpHandlerAdapter servlet) {
169169
InetSocketAddress address = new InetSocketAddress(getAddress(), port);
170170
Server server = new Server(getThreadPool());
171171
server.addConnector(createConnector(address, server));
172+
server.setStopTimeout(0);
172173
ServletHolder servletHolder = new ServletHolder(servlet);
173174
servletHolder.setAsyncSupported(true);
174175
ServletContextHandler contextHandler = new ServletContextHandler(server, "/", false, false);

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/jetty/JettyServletWebServerFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2021 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -165,6 +165,7 @@ public WebServer getWebServer(ServletContextInitializer... initializers) {
165165
private Server createServer(InetSocketAddress address) {
166166
Server server = new Server(getThreadPool());
167167
server.setConnectors(new Connector[] { createConnector(address, server) });
168+
server.setStopTimeout(0);
168169
return server;
169170
}
170171

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/reactive/server/AbstractReactiveWebServerFactoryTests.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -437,6 +437,30 @@ void givenAnInflightRequestWhenTheServerIsStoppedThenGracefulShutdownCallbackIsC
437437
blockingHandler.completeOne();
438438
}
439439

440+
@Test
441+
void whenARequestIsActiveAfterGracefulShutdownEndsThenStopWillComplete() throws InterruptedException {
442+
AbstractReactiveWebServerFactory factory = getFactory();
443+
factory.setShutdown(Shutdown.GRACEFUL);
444+
BlockingHandler blockingHandler = new BlockingHandler();
445+
this.webServer = factory.getWebServer(blockingHandler);
446+
this.webServer.start();
447+
Mono<ResponseEntity<Void>> request = getWebClient(this.webServer.getPort()).build().get().retrieve()
448+
.toBodilessEntity();
449+
AtomicReference<ResponseEntity<Void>> responseReference = new AtomicReference<>();
450+
CountDownLatch responseLatch = new CountDownLatch(1);
451+
request.subscribe((response) -> {
452+
responseReference.set(response);
453+
responseLatch.countDown();
454+
});
455+
blockingHandler.awaitQueue();
456+
AtomicReference<GracefulShutdownResult> result = new AtomicReference<>();
457+
this.webServer.shutDownGracefully(result::set);
458+
this.webServer.stop();
459+
Awaitility.await().atMost(Duration.ofSeconds(30))
460+
.until(() -> GracefulShutdownResult.REQUESTS_ACTIVE == result.get());
461+
blockingHandler.completeOne();
462+
}
463+
440464
@Test
441465
void whenARequestIsActiveThenStopWillComplete() throws InterruptedException, BrokenBarrierException {
442466
AbstractReactiveWebServerFactory factory = getFactory();

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/server/AbstractServletWebServerFactoryTests.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,31 @@ void whenARequestIsActiveThenStopWillComplete() throws InterruptedException, Bro
11191119
}
11201120
}
11211121

1122+
@Test
1123+
void whenARequestIsActiveAfterGracefulShutdownEndsThenStopWillComplete()
1124+
throws InterruptedException, BrokenBarrierException {
1125+
AbstractServletWebServerFactory factory = getFactory();
1126+
factory.setShutdown(Shutdown.GRACEFUL);
1127+
BlockingServlet blockingServlet = new BlockingServlet();
1128+
this.webServer = factory
1129+
.getWebServer((context) -> context.addServlet("blockingServlet", blockingServlet).addMapping("/"));
1130+
this.webServer.start();
1131+
int port = this.webServer.getPort();
1132+
initiateGetRequest(port, "/");
1133+
blockingServlet.awaitQueue();
1134+
AtomicReference<GracefulShutdownResult> result = new AtomicReference<>();
1135+
this.webServer.shutDownGracefully(result::set);
1136+
this.webServer.stop();
1137+
Awaitility.await().atMost(Duration.ofSeconds(30))
1138+
.until(() -> GracefulShutdownResult.REQUESTS_ACTIVE == result.get());
1139+
try {
1140+
blockingServlet.admitOne();
1141+
}
1142+
catch (RuntimeException ex) {
1143+
1144+
}
1145+
}
1146+
11221147
protected Future<Object> initiateGetRequest(int port, String path) {
11231148
return initiateGetRequest(HttpClients.createMinimal(), port, path);
11241149
}

0 commit comments

Comments
 (0)