Commit cc3aea2b authored by Andy Wilkinson's avatar Andy Wilkinson

Prevent Jetty’s singleton shutdown thread from breaking restarts

By default, Jetty uses a singleton shutdown thread, registered as a
shutdown hook, to stop its components. This single thread breaks the
restart logic in devtools as a second restart causes a second attempt to
start the singleton shutdown thread which fails with an
IllegalStateException. This processing is unnecessary in a Spring Boot
application as the application context’s lifecycle when ensure that
Jetty is shutdown.

This commit updates the embedded Jetty container to remove its
components from Jetty’s shutdown thread. This leaves the thread with
no components to manage at which point it removes its registration as a
shutdown hook.

Closes gh-3343
parent a09a29be
...@@ -16,8 +16,10 @@ ...@@ -16,8 +16,10 @@
package org.springframework.boot.autoconfigure.websocket; package org.springframework.boot.autoconfigure.websocket;
import org.eclipse.jetty.util.thread.ShutdownThread;
import org.eclipse.jetty.webapp.AbstractConfiguration; import org.eclipse.jetty.webapp.AbstractConfiguration;
import org.eclipse.jetty.webapp.WebAppContext; import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer; import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
...@@ -38,7 +40,9 @@ public class JettyWebSocketContainerCustomizer extends ...@@ -38,7 +40,9 @@ public class JettyWebSocketContainerCustomizer extends
@Override @Override
public void configure(WebAppContext context) throws Exception { public void configure(WebAppContext context) throws Exception {
WebSocketServerContainerInitializer.configureContext(context); ServerContainer serverContainer = WebSocketServerContainerInitializer
.configureContext(context);
ShutdownThread.deregister(serverContainer);
} }
}); });
......
...@@ -81,6 +81,7 @@ public class JettyEmbeddedServletContainer implements EmbeddedServletContainer { ...@@ -81,6 +81,7 @@ public class JettyEmbeddedServletContainer implements EmbeddedServletContainer {
// Start the server so that the ServletContext is available // Start the server so that the ServletContext is available
this.server.start(); this.server.start();
this.server.setStopAtShutdown(false);
} }
catch (Exception ex) { catch (Exception ex) {
// Ensure process isn't left running // Ensure process isn't left running
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment