Merge pull request #3441 from eclipse/jetty-9.4.x-3440-StopOnUnavailable
Issue #3440 Stop on Unavailable
This commit is contained in:
commit
74233d5711
|
@ -98,7 +98,7 @@ public class LikeJettyXml
|
|||
Server server = new Server(threadPool);
|
||||
|
||||
// Scheduler
|
||||
server.addBean(new ScheduledExecutorScheduler());
|
||||
server.addBean(new ScheduledExecutorScheduler(null,false));
|
||||
|
||||
// HTTP Configuration
|
||||
HttpConfiguration http_config = new HttpConfiguration();
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()), false);
|
||||
addBean(scheduler);
|
||||
}
|
||||
|
||||
if (bufferPool == null)
|
||||
addBean(bufferPool = new MappedByteBufferPool());
|
||||
{
|
||||
bufferPool = new MappedByteBufferPool();
|
||||
addBean(bufferPool);
|
||||
}
|
||||
|
||||
addBean(selector = newSelectorManager());
|
||||
selector.setConnectTimeout(getConnectTimeout());
|
||||
|
|
|
@ -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()),false);
|
||||
if (pool==null)
|
||||
pool=_server.getBean(ByteBufferPool.class);
|
||||
_byteBufferPool = pool!=null?pool:new ArrayByteBufferPool();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -121,7 +121,7 @@ public class HouseKeeper extends AbstractLifeCycle
|
|||
|
||||
if (_scheduler == null)
|
||||
{
|
||||
_scheduler = new ScheduledExecutorScheduler();
|
||||
_scheduler = new ScheduledExecutorScheduler(String.format("Session-HouseKeeper-%x",hashCode()),false);
|
||||
_ownScheduler = true;
|
||||
_scheduler.start();
|
||||
if (LOG.isDebugEnabled()) LOG.debug("Using own scheduler for scavenging");
|
||||
|
|
|
@ -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()), false);
|
||||
_ownScheduler = true;
|
||||
_scheduler.start();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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,60 @@ 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);
|
||||
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
|
||||
{
|
||||
throw new Exception("Test start failure");
|
||||
}
|
||||
};
|
||||
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
|
||||
{
|
||||
server.start();
|
||||
fail();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
assertThat(e.getMessage(),is("Test start failure"));
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
|
|
|
@ -281,7 +281,7 @@ public class DoSFilter implements Filter
|
|||
{
|
||||
try
|
||||
{
|
||||
Scheduler result = new ScheduledExecutorScheduler();
|
||||
Scheduler result = new ScheduledExecutorScheduler(String.format("DoS-Scheduler-%x",hashCode()),false);
|
||||
result.start();
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -96,35 +96,64 @@ 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
|
||||
List<Bean> reverse = new ArrayList<>(_beans);
|
||||
Collections.reverse(reverse);
|
||||
for (Bean b : reverse)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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<Integer, WebSocketHandshake> 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()),false);
|
||||
private final List<WebSocketSessionListener> listeners = new ArrayList<>();
|
||||
private final String supportedVersions;
|
||||
private final WebSocketPolicy defaultPolicy;
|
||||
|
|
Loading…
Reference in New Issue