From 5aafbc2a3b1d633f8aa436025943146b10fae5ff Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Wed, 1 Mar 2017 22:36:14 -0800 Subject: [PATCH] Refine engine counter logic Update counter logic to prevent negative values. Since the stop method can now be called more than once, it was possible for the counter to move into negative values. See gh-8227 --- .../TomcatEmbeddedServletContainer.java | 51 +++++++++++-------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainer.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainer.java index b97a66574d..b9a59b4fc2 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainer.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainer.java @@ -90,28 +90,34 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer synchronized (this.monitor) { try { addInstanceIdToEngineName(); - - // Remove service connectors to that protocol binding doesn't happen yet - removeServiceConnectors(); - - // Start the server to trigger initialization listeners - this.tomcat.start(); - - // We can re-throw failure exception directly in the main thread - rethrowDeferredStartupExceptions(); - - Context context = findContext(); try { - ContextBindings.bindClassLoader(context, getNamingToken(context), - getClass().getClassLoader()); - } - catch (NamingException ex) { - // Naming is not enabled. Continue - } + // Remove service connectors to that protocol binding doesn't happen + // yet + removeServiceConnectors(); - // Unlike Jetty, all Tomcat threads are daemon threads. We create a - // blocking non-daemon to stop immediate shutdown - startDaemonAwaitThread(); + // Start the server to trigger initialization listeners + this.tomcat.start(); + + // We can re-throw failure exception directly in the main thread + rethrowDeferredStartupExceptions(); + + Context context = findContext(); + try { + ContextBindings.bindClassLoader(context, getNamingToken(context), + getClass().getClassLoader()); + } + catch (NamingException ex) { + // Naming is not enabled. Continue + } + + // Unlike Jetty, all Tomcat threads are daemon threads. We create a + // blocking non-daemon to stop immediate shutdown + startDaemonAwaitThread(); + } + catch (Exception ex) { + containerCounter.decrementAndGet(); + throw ex; + } } catch (Exception ex) { throw new EmbeddedServletContainerException( @@ -279,6 +285,7 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer @Override public void stop() throws EmbeddedServletContainerException { synchronized (this.monitor) { + boolean wasStarted = this.started; try { this.started = false; try { @@ -294,7 +301,9 @@ public class TomcatEmbeddedServletContainer implements EmbeddedServletContainer "Unable to stop embedded Tomcat", ex); } finally { - containerCounter.decrementAndGet(); + if (wasStarted) { + containerCounter.decrementAndGet(); + } } } }