Skip to content

Commit fded872

Browse files
committed
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
2 parents c06a977 + 5aafbc2 commit fded872

File tree

5 files changed

+56
-33
lines changed

5 files changed

+56
-33
lines changed

spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainer.java

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,6 @@ else if (handler instanceof HandlerCollection) {
205205
@Override
206206
public void stop() {
207207
synchronized (this.monitor) {
208-
if (!this.started) {
209-
return;
210-
}
211208
this.started = false;
212209
try {
213210
this.server.stop();

spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainer.java

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -90,28 +90,34 @@ private void initialize() throws EmbeddedServletContainerException {
9090
synchronized (this.monitor) {
9191
try {
9292
addInstanceIdToEngineName();
93+
try {
94+
// Remove service connectors to that protocol binding doesn't happen
95+
// yet
96+
removeServiceConnectors();
9397

94-
// Remove service connectors to that protocol binding doesn't happen yet
95-
removeServiceConnectors();
98+
// Start the server to trigger initialization listeners
99+
this.tomcat.start();
96100

97-
// Start the server to trigger initialization listeners
98-
this.tomcat.start();
101+
// We can re-throw failure exception directly in the main thread
102+
rethrowDeferredStartupExceptions();
99103

100-
// We can re-throw failure exception directly in the main thread
101-
rethrowDeferredStartupExceptions();
104+
Context context = findContext();
105+
try {
106+
ContextBindings.bindClassLoader(context, getNamingToken(context),
107+
getClass().getClassLoader());
108+
}
109+
catch (NamingException ex) {
110+
// Naming is not enabled. Continue
111+
}
102112

103-
Context context = findContext();
104-
try {
105-
ContextBindings.bindClassLoader(context, getNamingToken(context),
106-
getClass().getClassLoader());
113+
// Unlike Jetty, all Tomcat threads are daemon threads. We create a
114+
// blocking non-daemon to stop immediate shutdown
115+
startDaemonAwaitThread();
107116
}
108-
catch (NamingException ex) {
109-
// Naming is not enabled. Continue
117+
catch (Exception ex) {
118+
containerCounter.decrementAndGet();
119+
throw ex;
110120
}
111-
112-
// Unlike Jetty, all Tomcat threads are daemon threads. We create a
113-
// blocking non-daemon to stop immediate shutdown
114-
startDaemonAwaitThread();
115121
}
116122
catch (Exception ex) {
117123
throw new EmbeddedServletContainerException(
@@ -279,9 +285,7 @@ Map<Service, Connector[]> getServiceConnectors() {
279285
@Override
280286
public void stop() throws EmbeddedServletContainerException {
281287
synchronized (this.monitor) {
282-
if (!this.started) {
283-
return;
284-
}
288+
boolean wasStarted = this.started;
285289
try {
286290
this.started = false;
287291
try {
@@ -297,7 +301,9 @@ public void stop() throws EmbeddedServletContainerException {
297301
"Unable to stop embedded Tomcat", ex);
298302
}
299303
finally {
300-
containerCounter.decrementAndGet();
304+
if (wasStarted) {
305+
containerCounter.decrementAndGet();
306+
}
301307
}
302308
}
303309
}

spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactoryTests.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,16 @@ public void startCalledTwice() throws Exception {
170170
assertThat(this.output.toString()).containsOnlyOnce("started on port");
171171
}
172172

173+
@Test
174+
public void stopCalledTwice() throws Exception {
175+
AbstractEmbeddedServletContainerFactory factory = getFactory();
176+
this.container = factory
177+
.getEmbeddedServletContainer(exampleServletRegistration());
178+
this.container.start();
179+
this.container.stop();
180+
this.container.stop();
181+
}
182+
173183
@Test
174184
public void emptyServerWhenPortIsMinusOne() throws Exception {
175185
AbstractEmbeddedServletContainerFactory factory = getFactory();
@@ -311,16 +321,6 @@ public void contextRootPathMustNotBeSlash() throws Exception {
311321
getFactory().setContextPath("/");
312322
}
313323

314-
@Test
315-
public void doubleStop() throws Exception {
316-
AbstractEmbeddedServletContainerFactory factory = getFactory();
317-
this.container = factory
318-
.getEmbeddedServletContainer(exampleServletRegistration());
319-
this.container.start();
320-
this.container.stop();
321-
this.container.stop();
322-
}
323-
324324
@Test
325325
public void multipleConfigurations() throws Exception {
326326
AbstractEmbeddedServletContainerFactory factory = getFactory();

spring-boot/src/test/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactoryTests.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,16 @@ public void sslCiphersConfiguration() throws Exception {
143143
.isEmpty();
144144
}
145145

146+
@Test
147+
public void stopCalledWithoutStart() throws Exception {
148+
JettyEmbeddedServletContainerFactory factory = getFactory();
149+
this.container = factory
150+
.getEmbeddedServletContainer(exampleServletRegistration());
151+
this.container.stop();
152+
Server server = ((JettyEmbeddedServletContainer) this.container).getServer();
153+
assertThat(server.isStopped()).isTrue();
154+
}
155+
146156
@Override
147157
protected void addConnector(final int port,
148158
AbstractEmbeddedServletContainerFactory factory) {

spring-boot/src/test/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactoryTests.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,16 @@ public void startupFailureDoesNotResultInUnstoppedThreadsBeingReported()
352352
.doesNotContain("appears to have started a thread named [main]");
353353
}
354354

355+
@Test
356+
public void stopCalledWithoutStart() throws Exception {
357+
TomcatEmbeddedServletContainerFactory factory = getFactory();
358+
this.container = factory
359+
.getEmbeddedServletContainer(exampleServletRegistration());
360+
this.container.stop();
361+
Tomcat tomcat = ((TomcatEmbeddedServletContainer) this.container).getTomcat();
362+
assertThat(tomcat.getServer().getState()).isSameAs(LifecycleState.DESTROYED);
363+
}
364+
355365
@Override
356366
protected void addConnector(int port,
357367
AbstractEmbeddedServletContainerFactory factory) {

0 commit comments

Comments
 (0)