Commit d7d2404c authored by Andy Wilkinson's avatar Andy Wilkinson

Ensure that Tomcat does not report unstopped main thread when startup fails

Following the changes made in ff99bb07, Tomcat’s WebAppClassLoader is
set as the thread context class loader of the main thread. If Tomcat
was stopped while the main thread was still running (typically as a 
result of a startup failure), this had the unwanted side-effect of
causing Tomcat to report that the application had started a thread named
main and had failed to stop it.

This commit updates TomcatEmbeddedServletContainer so that, during stop
processing, the current thread’s context class loader is reset before
Tomcat is stopped. This prevents Tomcat from incorrectly believe that
the application has started and failed to stop the main thread.

Closes gh-5357
parent cc2f6f4b
......@@ -155,6 +155,7 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
}
};
awaitThread.setContextClassLoader(getClass().getClassLoader());
awaitThread.setDaemon(false);
awaitThread.start();
}
......@@ -191,13 +192,21 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
private void stopSilently() {
try {
this.tomcat.stop();
stopTomcat();
}
catch (LifecycleException ex) {
// Ignore
}
}
private void stopTomcat() throws LifecycleException {
if (Thread.currentThread()
.getContextClassLoader() instanceof TomcatEmbeddedWebappClassLoader) {
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
}
this.tomcat.stop();
}
private void addPreviouslyRemovedConnectors() {
Service[] services = this.tomcat.getServer().findServices();
for (Service service : services) {
......@@ -246,7 +255,7 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
public synchronized void stop() throws EmbeddedServletContainerException {
try {
try {
this.tomcat.stop();
stopTomcat();
this.tomcat.destroy();
}
catch (LifecycleException ex) {
......@@ -258,10 +267,6 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
ex);
}
finally {
if (Thread.currentThread()
.getContextClassLoader() instanceof TomcatEmbeddedWebappClassLoader) {
Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
}
containerCounter.decrementAndGet();
}
}
......
......@@ -37,6 +37,7 @@ import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.valves.RemoteIpValve;
import org.apache.coyote.http11.AbstractHttp11JsseProtocol;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.InOrder;
......@@ -44,6 +45,7 @@ import org.springframework.boot.context.embedded.AbstractEmbeddedServletContaine
import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactoryTests;
import org.springframework.boot.context.embedded.EmbeddedServletContainerException;
import org.springframework.boot.context.embedded.Ssl;
import org.springframework.boot.testutil.OutputCapture;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.util.SocketUtils;
......@@ -67,6 +69,9 @@ import static org.mockito.Mockito.verify;
public class TomcatEmbeddedServletContainerFactoryTests
extends AbstractEmbeddedServletContainerFactoryTests {
@Rule
public OutputCapture outputCapture = new OutputCapture();
@Override
protected TomcatEmbeddedServletContainerFactory getFactory() {
return new TomcatEmbeddedServletContainerFactory(0);
......@@ -335,6 +340,16 @@ public class TomcatEmbeddedServletContainerFactoryTests
}
@Test
public void startupFailureDoesNotResultInUnstoppedThreadsBeingReported()
throws IOException {
super.portClashOfPrimaryConnectorResultsInPortInUseException();
String string = this.outputCapture.toString();
assertThat(string)
.doesNotContain("appears to have started a thread named [main]");
}
@Override
protected void addConnector(int port,
AbstractEmbeddedServletContainerFactory factory) {
......
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