Skip to content

Commit 0cb86e1

Browse files
committed
Tolerate multiple calls to UndertowWebServer.destroy()
Undertow's DeploymentManagerImpl is not idempotent. Calling undeploy() multiple times will result in an NPE. Similarly, calling start() or stop() after undeploy() will also result in an NPE. This commit protects against this by checking that the deployment manager's state is not UNDEPLOYED before calling stop() and undeploy(). Fixes gh-48446
1 parent a6986a4 commit 0cb86e1

File tree

2 files changed

+21
-6
lines changed

2 files changed

+21
-6
lines changed

spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/undertow/DeploymentManagerHttpHandlerFactory.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import io.undertow.server.HttpHandler;
2323
import io.undertow.server.HttpServerExchange;
2424
import io.undertow.servlet.api.DeploymentManager;
25+
import io.undertow.servlet.api.DeploymentManager.State;
2526
import jakarta.servlet.ServletException;
2627

2728
import org.springframework.util.Assert;
@@ -76,12 +77,14 @@ public void handleRequest(HttpServerExchange exchange) throws Exception {
7677

7778
@Override
7879
public void close() throws IOException {
79-
try {
80-
this.deploymentManager.stop();
81-
this.deploymentManager.undeploy();
82-
}
83-
catch (ServletException ex) {
84-
throw new RuntimeException(ex);
80+
if (this.deploymentManager.getState() != State.UNDEPLOYED) {
81+
try {
82+
this.deploymentManager.stop();
83+
this.deploymentManager.undeploy();
84+
}
85+
catch (ServletException ex) {
86+
throw new RuntimeException(ex);
87+
}
8588
}
8689
}
8790

spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/undertow/UndertowServletWebServerFactoryTests.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import org.springframework.boot.web.server.GracefulShutdownResult;
5555
import org.springframework.boot.web.server.PortInUseException;
5656
import org.springframework.boot.web.server.Shutdown;
57+
import org.springframework.boot.web.server.WebServer;
5758
import org.springframework.boot.web.servlet.ServletRegistrationBean;
5859
import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactory;
5960
import org.springframework.boot.web.servlet.server.AbstractServletWebServerFactoryTests;
@@ -64,6 +65,7 @@
6465
import static org.assertj.core.api.Assertions.assertThat;
6566
import static org.assertj.core.api.Assertions.assertThatIOException;
6667
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
68+
import static org.assertj.core.api.Assertions.assertThatNoException;
6769
import static org.hamcrest.Matchers.is;
6870
import static org.mockito.ArgumentMatchers.any;
6971
import static org.mockito.Mockito.inOrder;
@@ -320,6 +322,16 @@ void sslRestrictedProtocolsRSATLS11Failure() {
320322
.isInstanceOfAny(SSLException.class, SocketException.class);
321323
}
322324

325+
@Test
326+
void multipleCallsToDestroyAreTolerated() {
327+
AbstractServletWebServerFactory factory = getFactory();
328+
factory.setPort(0);
329+
WebServer webServer = factory.getWebServer();
330+
webServer.start();
331+
webServer.destroy();
332+
assertThatNoException().isThrownBy(webServer::destroy);
333+
}
334+
323335
@Override
324336
protected JspServlet getJspServlet() {
325337
return null; // Undertow does not support JSPs

0 commit comments

Comments
 (0)