From 375ad81f4b91ab99dd06a950ab01c4d367c20d5d Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 7 Mar 2019 15:10:53 +1100 Subject: [PATCH 1/6] Issue #3440 Stop on Unavailable + Any schedulers created are named (for ease of debug) and daemon so they do not stop the JVM exiting. + If the server.doStart() fails, it calls server.doStop to ensure connectors are stopped, ports are free etc. + cleanup of addBean handling of scheduler in proxy Signed-off-by: Greg Wilkins --- .../org/eclipse/jetty/embedded/LikeJettyXml.java | 2 +- .../org/eclipse/jetty/embedded/OneWebApp.java | 5 ++--- .../org/eclipse/jetty/proxy/ConnectHandler.java | 16 ++++++++++++---- .../eclipse/jetty/server/AbstractConnector.java | 2 +- .../java/org/eclipse/jetty/server/Server.java | 13 ++++++++++++- .../jetty/server/handler/ContextHandler.java | 2 +- .../jetty/server/session/HouseKeeper.java | 2 +- .../jetty/server/session/SessionHandler.java | 7 +++---- .../org/eclipse/jetty/servlets/DoSFilter.java | 2 +- .../websocket/server/WebSocketServerFactory.java | 3 ++- 10 files changed, 36 insertions(+), 18 deletions(-) diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java index f2fe8dcffe4..5f5360ce919 100644 --- a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java @@ -98,7 +98,7 @@ public class LikeJettyXml Server server = new Server(threadPool); // Scheduler - server.addBean(new ScheduledExecutorScheduler()); + server.addBean(new ScheduledExecutorScheduler(null,true)); // HTTP Configuration HttpConfiguration http_config = new HttpConfiguration(); diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/OneWebApp.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/OneWebApp.java index d4495c6cc78..e6457c784c0 100644 --- a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/OneWebApp.java +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/OneWebApp.java @@ -23,7 +23,6 @@ import java.lang.management.ManagementFactory; import org.eclipse.jetty.jmx.MBeanContainer; import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.handler.AllowSymLinkAliasChecker; import org.eclipse.jetty.webapp.WebAppContext; public class OneWebApp @@ -58,11 +57,11 @@ public class OneWebApp // the server so it is aware of where to send the appropriate requests. server.setHandler(webapp); - // Start things up! + // Start things up! server.start(); server.dumpStdErr(); - + // The use of server.join() the will make the current thread join and // wait until the server is done executing. // See http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#join() diff --git a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java index f096401cf35..f14756855c9 100644 --- a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java +++ b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java @@ -44,7 +44,6 @@ import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.ManagedSelector; import org.eclipse.jetty.io.MappedByteBufferPool; -import org.eclipse.jetty.io.SelectChannelEndPoint; import org.eclipse.jetty.io.SelectorManager; import org.eclipse.jetty.io.SocketChannelEndPoint; import org.eclipse.jetty.server.Handler; @@ -56,7 +55,6 @@ import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.HostPort; import org.eclipse.jetty.util.Promise; -import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler; @@ -106,6 +104,7 @@ public class ConnectHandler extends HandlerWrapper public void setScheduler(Scheduler scheduler) { + updateBean(this.scheduler,scheduler); this.scheduler = scheduler; } @@ -116,6 +115,7 @@ public class ConnectHandler extends HandlerWrapper public void setByteBufferPool(ByteBufferPool bufferPool) { + updateBean(this.bufferPool, bufferPool); this.bufferPool = bufferPool; } @@ -168,10 +168,18 @@ public class ConnectHandler extends HandlerWrapper executor = getServer().getThreadPool(); if (scheduler == null) - addBean(scheduler = new ScheduledExecutorScheduler()); + { + scheduler = getServer().getBean(Scheduler.class); + if (scheduler == null) + scheduler = new ScheduledExecutorScheduler(String.format("Proxy-Scheduler-%x", hashCode()), true); + addBean(scheduler); + } if (bufferPool == null) - addBean(bufferPool = new MappedByteBufferPool()); + { + bufferPool = new MappedByteBufferPool(); + addBean(bufferPool); + } addBean(selector = newSelectorManager()); selector.setConnectTimeout(getConnectTimeout()); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java index d84f52c8219..65df989dbce 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java @@ -183,7 +183,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co _executor=executor!=null?executor:_server.getThreadPool(); if (scheduler==null) scheduler=_server.getBean(Scheduler.class); - _scheduler=scheduler!=null?scheduler:new ScheduledExecutorScheduler(); + _scheduler=scheduler!=null?scheduler:new ScheduledExecutorScheduler(String.format("Connector-Scheduler-%x",hashCode()),true); if (pool==null) pool=_server.getBean(ByteBufferPool.class); _byteBufferPool = pool!=null?pool:new ArrayByteBufferPool(); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index 7ca34c3a9b4..664c2e4511f 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -402,7 +402,18 @@ public class Server extends HandlerWrapper implements Attributes if (isDumpAfterStart()) dumpStdErr(); - mex.ifExceptionThrow(); + if (mex.size()>0) + { + try + { + doStop(); + } + catch(Throwable e) + { + mex.add(e); + } + mex.ifExceptionThrow(); + } LOG.info(String.format("Started @%dms",Uptime.getUptime())); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 236354be226..b2fd1f42cb4 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -1148,7 +1148,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu case UNAVAILABLE: baseRequest.setHandled(true); response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); - return false; + return true; default: if ((DispatcherType.REQUEST.equals(dispatch) && baseRequest.isHandled())) return false; diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HouseKeeper.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HouseKeeper.java index 82bc5e1f4d1..999fcaf1f87 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HouseKeeper.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HouseKeeper.java @@ -121,7 +121,7 @@ public class HouseKeeper extends AbstractLifeCycle if (_scheduler == null) { - _scheduler = new ScheduledExecutorScheduler(); + _scheduler = new ScheduledExecutorScheduler(String.format("Session-HouseKeeper-%x",hashCode()),true); _ownScheduler = true; _scheduler.start(); if (LOG.isDebugEnabled()) LOG.debug("Using own scheduler for scavenging"); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java index 1188c2e7d99..4592960c422 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java @@ -18,8 +18,6 @@ package org.eclipse.jetty.server.session; -import static java.lang.Math.round; - import java.io.IOException; import java.util.Arrays; import java.util.Collections; @@ -67,6 +65,8 @@ import org.eclipse.jetty.util.thread.Locker.Lock; import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler; import org.eclipse.jetty.util.thread.Scheduler; +import static java.lang.Math.round; + /* ------------------------------------------------------------ */ /** * SessionHandler. @@ -523,10 +523,9 @@ public class SessionHandler extends ScopedHandler _scheduler = server.getBean(Scheduler.class); if (_scheduler == null) { - _scheduler = new ScheduledExecutorScheduler(); + _scheduler = new ScheduledExecutorScheduler(String.format("Session-Scheduler-%x",hashCode()), true); _ownScheduler = true; _scheduler.start(); - } } diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java index c37d529a890..05f3fe82772 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java @@ -281,7 +281,7 @@ public class DoSFilter implements Filter { try { - Scheduler result = new ScheduledExecutorScheduler(); + Scheduler result = new ScheduledExecutorScheduler(String.format("DoS-Scheduler-%x",hashCode()),true); result.start(); return result; } diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java index b0bfec349db..92df73ba83f 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java @@ -30,6 +30,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.Executor; + import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -86,7 +87,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc private final ClassLoader contextClassloader; private final Map handshakes = new HashMap<>(); // TODO: obtain shared (per server scheduler, somehow) - private final Scheduler scheduler = new ScheduledExecutorScheduler(); + private final Scheduler scheduler = new ScheduledExecutorScheduler(String.format("WebSocket-Scheduler-%x",hashCode()),true); private final List listeners = new ArrayList<>(); private final String supportedVersions; private final WebSocketPolicy defaultPolicy; From 054d7f240eb17ff8597f5d46b524bae0f0665be2 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 11 Mar 2019 16:41:20 +1100 Subject: [PATCH 2/6] Issue #3440 Stop on Unavailable + cleanup after review Signed-off-by: Greg Wilkins --- .../java/org/eclipse/jetty/server/Server.java | 20 +++--- .../jetty/server/GracefulStopTest.java | 62 +++++++++++++++---- 2 files changed, 61 insertions(+), 21 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index 664c2e4511f..d930ed2b65b 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -387,15 +387,18 @@ public class Server extends HandlerWrapper implements Attributes } // start connectors last - for (Connector connector : _connectors) + if (mex.size()==0) { - try + for (Connector connector : _connectors) { - connector.start(); - } - catch(Throwable e) - { - mex.add(e); + try + { + connector.start(); + } + catch (Throwable e) + { + mex.add(e); + } } } @@ -412,9 +415,10 @@ public class Server extends HandlerWrapper implements Attributes { mex.add(e); } - mex.ifExceptionThrow(); } + mex.ifExceptionThrow(); + LOG.info(String.format("Started @%dms",Uptime.getUptime())); } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java index b6a83d254a7..dc7e601d7c1 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java @@ -18,18 +18,6 @@ package org.eclipse.jetty.server; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.greaterThan; -import static org.hamcrest.Matchers.instanceOf; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.lessThan; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.notNullValue; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.condition.OS.WINDOWS; - import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -54,18 +42,32 @@ import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.server.LocalConnector.LocalEndPoint; import org.eclipse.jetty.server.handler.AbstractHandler; import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.server.handler.ContextHandlerCollection; import org.eclipse.jetty.server.handler.StatisticsHandler; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.thread.QueuedThreadPool; import org.hamcrest.Matcher; import org.hamcrest.Matchers; - import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.condition.DisabledOnOs; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.greaterThan; +import static org.hamcrest.Matchers.instanceOf; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.lessThan; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; +import static org.junit.jupiter.api.condition.OS.WINDOWS; + public class GracefulStopTest { /** @@ -657,6 +659,40 @@ public class GracefulStopTest assertThat(response,Matchers.not(Matchers.containsString("Connection: close"))); assertTrue(latch.await(10,TimeUnit.SECONDS)); } + + @Test + public void testFailedStart() + { + Server server= new Server(); + + LocalConnector connector = new LocalConnector(server); + server.addConnector(connector); + + ContextHandlerCollection contexts = new ContextHandlerCollection(); + server.setHandler(contexts); + ContextHandler context0 = new ContextHandler(server,"/zero"); + ContextHandler context1 = new ContextHandler(server,"/one") + { + @Override + protected void doStart() throws Exception + { + throw new Exception("Test start failure"); + } + }; + contexts.setHandlers(new Handler[]{context0,context1}); + + try + { + server.start(); + fail(); + } + catch(Exception e) + { + assertThat(e.getMessage(),is("Test start failure")); + } + + server.getContainedBeans(LifeCycle.class).stream().forEach(lc -> assertTrue(!lc.isRunning())); + } static class NoopHandler extends AbstractHandler { From a9707471a053a753330d2c3767930c9d5283dd65 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Mon, 11 Mar 2019 17:10:03 +1100 Subject: [PATCH 3/6] Issue #3440 Stop on Unavailable + ContainerLifeCycle stops started beans on failure. Signed-off-by: Greg Wilkins --- .../java/org/eclipse/jetty/server/Server.java | 12 --- .../jetty/server/GracefulStopTest.java | 3 +- .../util/component/ContainerLifeCycle.java | 73 +++++++++++++------ 3 files changed, 52 insertions(+), 36 deletions(-) diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index d930ed2b65b..808882a8576 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -405,18 +405,6 @@ public class Server extends HandlerWrapper implements Attributes if (isDumpAfterStart()) dumpStdErr(); - if (mex.size()>0) - { - try - { - doStop(); - } - catch(Throwable e) - { - mex.add(e); - } - } - mex.ifExceptionThrow(); LOG.info(String.format("Started @%dms",Uptime.getUptime())); diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java index dc7e601d7c1..94935fcbb62 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java @@ -691,7 +691,8 @@ public class GracefulStopTest assertThat(e.getMessage(),is("Test start failure")); } - server.getContainedBeans(LifeCycle.class).stream().forEach(lc -> assertTrue(!lc.isRunning())); + assertTrue(server.getContainedBeans(LifeCycle.class).stream().noneMatch(LifeCycle::isRunning)); + assertTrue(server.getContainedBeans(LifeCycle.class).stream().anyMatch(LifeCycle::isFailed)); } static class NoopHandler extends AbstractHandler diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java index ad1c4d4aceb..7650fa9603c 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java @@ -96,35 +96,62 @@ public class ContainerLifeCycle extends AbstractLifeCycle implements Container, _doStarted = true; // start our managed and auto beans - for (Bean b : _beans) + try { - if (b._bean instanceof LifeCycle) + for (Bean b : _beans) { - LifeCycle l = (LifeCycle)b._bean; - switch(b._managed) + if (b._bean instanceof LifeCycle) { - case MANAGED: - if (!l.isRunning()) - start(l); - break; - - case AUTO: - if (l.isRunning()) - unmanage(b); - else - { - manage(b); - start(l); - } - break; - - default: - break; + LifeCycle l = (LifeCycle)b._bean; + switch (b._managed) + { + case MANAGED: + if (!l.isRunning()) + start(l); + break; + + case AUTO: + if (l.isRunning()) + unmanage(b); + else + { + manage(b); + start(l); + } + break; + + default: + break; + } } } - } - super.doStart(); + super.doStart(); + } + catch (Throwable t) + { + // on failure, stop any managed components that have been started + for (Bean b : _beans) + { + if (b._bean instanceof LifeCycle && b._managed == Managed.MANAGED) + { + LifeCycle l = (LifeCycle)b._bean; + if (l.isRunning()) + { + try + { + l.stop(); + } + catch(Throwable t2) + { + if (t2!=t) + t.addSuppressed(t2); + } + } + } + } + throw t; + } } /** From 76a37352f576da5834304bd68f87e1cac2e0b6f1 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 12 Mar 2019 09:21:19 +1100 Subject: [PATCH 4/6] Issue #3440 Stop on Unavailable + revert schedulers to non-daemon threads for now so this PR can proceed. Signed-off-by: Greg Wilkins --- .../src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java | 2 +- .../src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java | 2 +- .../main/java/org/eclipse/jetty/server/AbstractConnector.java | 2 +- .../main/java/org/eclipse/jetty/server/session/HouseKeeper.java | 2 +- .../java/org/eclipse/jetty/server/session/SessionHandler.java | 2 +- .../src/main/java/org/eclipse/jetty/servlets/DoSFilter.java | 2 +- .../eclipse/jetty/websocket/server/WebSocketServerFactory.java | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java index 5f5360ce919..3d5759e8d4e 100644 --- a/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java +++ b/examples/embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java @@ -98,7 +98,7 @@ public class LikeJettyXml Server server = new Server(threadPool); // Scheduler - server.addBean(new ScheduledExecutorScheduler(null,true)); + server.addBean(new ScheduledExecutorScheduler(null,false)); // HTTP Configuration HttpConfiguration http_config = new HttpConfiguration(); diff --git a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java index f14756855c9..6b7d39eed9b 100644 --- a/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java +++ b/jetty-proxy/src/main/java/org/eclipse/jetty/proxy/ConnectHandler.java @@ -171,7 +171,7 @@ public class ConnectHandler extends HandlerWrapper { scheduler = getServer().getBean(Scheduler.class); if (scheduler == null) - scheduler = new ScheduledExecutorScheduler(String.format("Proxy-Scheduler-%x", hashCode()), true); + scheduler = new ScheduledExecutorScheduler(String.format("Proxy-Scheduler-%x", hashCode()), false); addBean(scheduler); } diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java index 65df989dbce..1a92d1f630c 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java @@ -183,7 +183,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co _executor=executor!=null?executor:_server.getThreadPool(); if (scheduler==null) scheduler=_server.getBean(Scheduler.class); - _scheduler=scheduler!=null?scheduler:new ScheduledExecutorScheduler(String.format("Connector-Scheduler-%x",hashCode()),true); + _scheduler=scheduler!=null?scheduler:new ScheduledExecutorScheduler(String.format("Connector-Scheduler-%x",hashCode()),false); if (pool==null) pool=_server.getBean(ByteBufferPool.class); _byteBufferPool = pool!=null?pool:new ArrayByteBufferPool(); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HouseKeeper.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HouseKeeper.java index 999fcaf1f87..6e5faaa6b05 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HouseKeeper.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HouseKeeper.java @@ -121,7 +121,7 @@ public class HouseKeeper extends AbstractLifeCycle if (_scheduler == null) { - _scheduler = new ScheduledExecutorScheduler(String.format("Session-HouseKeeper-%x",hashCode()),true); + _scheduler = new ScheduledExecutorScheduler(String.format("Session-HouseKeeper-%x",hashCode()),false); _ownScheduler = true; _scheduler.start(); if (LOG.isDebugEnabled()) LOG.debug("Using own scheduler for scavenging"); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java index 4592960c422..c2263af8ff4 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java @@ -523,7 +523,7 @@ public class SessionHandler extends ScopedHandler _scheduler = server.getBean(Scheduler.class); if (_scheduler == null) { - _scheduler = new ScheduledExecutorScheduler(String.format("Session-Scheduler-%x",hashCode()), true); + _scheduler = new ScheduledExecutorScheduler(String.format("Session-Scheduler-%x",hashCode()), false); _ownScheduler = true; _scheduler.start(); } diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java index 05f3fe82772..7e0cc09fbc9 100644 --- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java +++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/DoSFilter.java @@ -281,7 +281,7 @@ public class DoSFilter implements Filter { try { - Scheduler result = new ScheduledExecutorScheduler(String.format("DoS-Scheduler-%x",hashCode()),true); + Scheduler result = new ScheduledExecutorScheduler(String.format("DoS-Scheduler-%x",hashCode()),false); result.start(); return result; } diff --git a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java index 92df73ba83f..f0197c862a1 100644 --- a/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java +++ b/jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java @@ -87,7 +87,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc private final ClassLoader contextClassloader; private final Map handshakes = new HashMap<>(); // TODO: obtain shared (per server scheduler, somehow) - private final Scheduler scheduler = new ScheduledExecutorScheduler(String.format("WebSocket-Scheduler-%x",hashCode()),true); + private final Scheduler scheduler = new ScheduledExecutorScheduler(String.format("WebSocket-Scheduler-%x",hashCode()),false); private final List listeners = new ArrayList<>(); private final String supportedVersions; private final WebSocketPolicy defaultPolicy; From 7b407ecb6cb2f21d76fc21e637f550c189cabeaa Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Tue, 12 Mar 2019 22:44:12 +1100 Subject: [PATCH 5/6] Issue #3440 Stop failed lifecycle stop in reverse order. Signed-off-by: Greg Wilkins --- .../org/eclipse/jetty/util/component/ContainerLifeCycle.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java b/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java index 7650fa9603c..9f5483eac8a 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/component/ContainerLifeCycle.java @@ -131,7 +131,9 @@ public class ContainerLifeCycle extends AbstractLifeCycle implements Container, catch (Throwable t) { // on failure, stop any managed components that have been started - for (Bean b : _beans) + List reverse = new ArrayList<>(_beans); + Collections.reverse(reverse); + for (Bean b : reverse) { if (b._bean instanceof LifeCycle && b._managed == Managed.MANAGED) { From ffdbbd1821e34e03af4dd0fd5385a495e85e9305 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 14 Mar 2019 09:07:16 +1100 Subject: [PATCH 6/6] Issue #3440 Stop failed lifecycle check that contexts after error are not started. Signed-off-by: Greg Wilkins --- .../jetty/server/GracefulStopTest.java | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java index 94935fcbb62..61226f45fb2 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java @@ -670,8 +670,16 @@ public class GracefulStopTest ContextHandlerCollection contexts = new ContextHandlerCollection(); server.setHandler(contexts); - ContextHandler context0 = new ContextHandler(server,"/zero"); - ContextHandler context1 = new ContextHandler(server,"/one") + AtomicBoolean context0Started = new AtomicBoolean(false); + ContextHandler context0 = new ContextHandler("/zero") + { + @Override + protected void doStart() throws Exception + { + context0Started.set(true); + } + }; + ContextHandler context1 = new ContextHandler("/one") { @Override protected void doStart() throws Exception @@ -679,7 +687,16 @@ public class GracefulStopTest throw new Exception("Test start failure"); } }; - contexts.setHandlers(new Handler[]{context0,context1}); + AtomicBoolean context2Started = new AtomicBoolean(false); + ContextHandler context2 = new ContextHandler("/two") + { + @Override + protected void doStart() throws Exception + { + context2Started.set(true); + } + }; + contexts.setHandlers(new Handler[]{context0, context1, context2}); try { @@ -693,6 +710,8 @@ public class GracefulStopTest assertTrue(server.getContainedBeans(LifeCycle.class).stream().noneMatch(LifeCycle::isRunning)); assertTrue(server.getContainedBeans(LifeCycle.class).stream().anyMatch(LifeCycle::isFailed)); + assertTrue(context0Started.get()); + assertFalse(context2Started.get()); } static class NoopHandler extends AbstractHandler