Commit fded8722 authored by Phillip Webb's avatar Phillip Webb

Merge pull request #8227 from mkw/gh-8224

* pr/8227:
  Refine engine counter logic
  Polish web containers stop contribution
  Ensure web containers are stopped after close
parents c06a9771 5aafbc2a
...@@ -205,9 +205,6 @@ public class JettyEmbeddedServletContainer implements EmbeddedServletContainer { ...@@ -205,9 +205,6 @@ public class JettyEmbeddedServletContainer implements EmbeddedServletContainer {
@Override @Override
public void stop() { public void stop() {
synchronized (this.monitor) { synchronized (this.monitor) {
if (!this.started) {
return;
}
this.started = false; this.started = false;
try { try {
this.server.stop(); this.server.stop();
......
...@@ -90,28 +90,34 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer ...@@ -90,28 +90,34 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
synchronized (this.monitor) { synchronized (this.monitor) {
try { try {
addInstanceIdToEngineName(); addInstanceIdToEngineName();
try {
// Remove service connectors to that protocol binding doesn't happen
// yet
removeServiceConnectors();
// Remove service connectors to that protocol binding doesn't happen yet // Start the server to trigger initialization listeners
removeServiceConnectors(); this.tomcat.start();
// Start the server to trigger initialization listeners // We can re-throw failure exception directly in the main thread
this.tomcat.start(); rethrowDeferredStartupExceptions();
// We can re-throw failure exception directly in the main thread Context context = findContext();
rethrowDeferredStartupExceptions(); try {
ContextBindings.bindClassLoader(context, getNamingToken(context),
getClass().getClassLoader());
}
catch (NamingException ex) {
// Naming is not enabled. Continue
}
Context context = findContext(); // Unlike Jetty, all Tomcat threads are daemon threads. We create a
try { // blocking non-daemon to stop immediate shutdown
ContextBindings.bindClassLoader(context, getNamingToken(context), startDaemonAwaitThread();
getClass().getClassLoader());
} }
catch (NamingException ex) { catch (Exception ex) {
// Naming is not enabled. Continue containerCounter.decrementAndGet();
throw ex;
} }
// Unlike Jetty, all Tomcat threads are daemon threads. We create a
// blocking non-daemon to stop immediate shutdown
startDaemonAwaitThread();
} }
catch (Exception ex) { catch (Exception ex) {
throw new EmbeddedServletContainerException( throw new EmbeddedServletContainerException(
...@@ -279,9 +285,7 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer ...@@ -279,9 +285,7 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
@Override @Override
public void stop() throws EmbeddedServletContainerException { public void stop() throws EmbeddedServletContainerException {
synchronized (this.monitor) { synchronized (this.monitor) {
if (!this.started) { boolean wasStarted = this.started;
return;
}
try { try {
this.started = false; this.started = false;
try { try {
...@@ -297,7 +301,9 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer ...@@ -297,7 +301,9 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer
"Unable to stop embedded Tomcat", ex); "Unable to stop embedded Tomcat", ex);
} }
finally { finally {
containerCounter.decrementAndGet(); if (wasStarted) {
containerCounter.decrementAndGet();
}
} }
} }
} }
......
...@@ -170,6 +170,16 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests { ...@@ -170,6 +170,16 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
assertThat(this.output.toString()).containsOnlyOnce("started on port"); assertThat(this.output.toString()).containsOnlyOnce("started on port");
} }
@Test
public void stopCalledTwice() throws Exception {
AbstractEmbeddedServletContainerFactory factory = getFactory();
this.container = factory
.getEmbeddedServletContainer(exampleServletRegistration());
this.container.start();
this.container.stop();
this.container.stop();
}
@Test @Test
public void emptyServerWhenPortIsMinusOne() throws Exception { public void emptyServerWhenPortIsMinusOne() throws Exception {
AbstractEmbeddedServletContainerFactory factory = getFactory(); AbstractEmbeddedServletContainerFactory factory = getFactory();
...@@ -311,16 +321,6 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests { ...@@ -311,16 +321,6 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
getFactory().setContextPath("/"); getFactory().setContextPath("/");
} }
@Test
public void doubleStop() throws Exception {
AbstractEmbeddedServletContainerFactory factory = getFactory();
this.container = factory
.getEmbeddedServletContainer(exampleServletRegistration());
this.container.start();
this.container.stop();
this.container.stop();
}
@Test @Test
public void multipleConfigurations() throws Exception { public void multipleConfigurations() throws Exception {
AbstractEmbeddedServletContainerFactory factory = getFactory(); AbstractEmbeddedServletContainerFactory factory = getFactory();
......
...@@ -143,6 +143,16 @@ public class JettyEmbeddedServletContainerFactoryTests ...@@ -143,6 +143,16 @@ public class JettyEmbeddedServletContainerFactoryTests
.isEmpty(); .isEmpty();
} }
@Test
public void stopCalledWithoutStart() throws Exception {
JettyEmbeddedServletContainerFactory factory = getFactory();
this.container = factory
.getEmbeddedServletContainer(exampleServletRegistration());
this.container.stop();
Server server = ((JettyEmbeddedServletContainer) this.container).getServer();
assertThat(server.isStopped()).isTrue();
}
@Override @Override
protected void addConnector(final int port, protected void addConnector(final int port,
AbstractEmbeddedServletContainerFactory factory) { AbstractEmbeddedServletContainerFactory factory) {
......
...@@ -352,6 +352,16 @@ public class TomcatEmbeddedServletContainerFactoryTests ...@@ -352,6 +352,16 @@ public class TomcatEmbeddedServletContainerFactoryTests
.doesNotContain("appears to have started a thread named [main]"); .doesNotContain("appears to have started a thread named [main]");
} }
@Test
public void stopCalledWithoutStart() throws Exception {
TomcatEmbeddedServletContainerFactory factory = getFactory();
this.container = factory
.getEmbeddedServletContainer(exampleServletRegistration());
this.container.stop();
Tomcat tomcat = ((TomcatEmbeddedServletContainer) this.container).getTomcat();
assertThat(tomcat.getServer().getState()).isSameAs(LifecycleState.DESTROYED);
}
@Override @Override
protected void addConnector(int port, protected void addConnector(int port,
AbstractEmbeddedServletContainerFactory factory) { 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