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 15b56554a75..f7ddb8ff21f 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 @@ -528,6 +528,34 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co return getConnectionFactory(_defaultProtocol); } + protected boolean handleAcceptFailure(Throwable previous, Throwable current) + { + if (isAccepting()) + { + if (previous == null) + LOG.warn(current); + else + LOG.debug(current); + } + else + { + LOG.ignore(current); + } + + try + { + // Arbitrary sleep to avoid spin looping. + // Subclasses may decide for a different + // sleep policy or closing the connector. + Thread.sleep(1000); + return true; + } + catch (Throwable x) + { + return false; + } + } + private class Acceptor implements Runnable { private final int _id; @@ -557,18 +585,20 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co try { + Throwable exception = null; while (isAccepting()) { try { accept(_id); + exception = null; } - catch (Throwable e) + catch (Throwable x) { - if (isAccepting()) - LOG.warn(e); + if (handleAcceptFailure(exception, x)) + exception = x; else - LOG.ignore(e); + break; } } } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTest.java index 1b3d8c43f3f..8d0c556bab2 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTest.java @@ -28,6 +28,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.util.Collection; +import java.util.concurrent.atomic.AtomicLong; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; @@ -40,6 +41,7 @@ import org.eclipse.jetty.server.handler.DefaultHandler; import org.eclipse.jetty.server.handler.HandlerList; import org.eclipse.jetty.toolchain.test.OS; import org.eclipse.jetty.util.IO; +import org.hamcrest.Matchers; import org.junit.Test; import static org.hamcrest.Matchers.anyOf; @@ -235,4 +237,32 @@ public class ServerConnectorTest assertEquals(2, connector.getBeans(ConnectionFactory.class).size()); assertEquals(proxy.getProtocol(), connector.getDefaultProtocol()); } + + @Test + public void testExceptionWhileAccepting() throws Exception + { + Server server = new Server(); + AtomicLong spins = new AtomicLong(); + ServerConnector connector = new ServerConnector(server) + { + @Override + public void accept(int acceptorID) throws IOException + { + spins.incrementAndGet(); + throw new IOException("explicitly_thrown_by_test"); + } + }; + server.addConnector(connector); + server.start(); + + try + { + Thread.sleep(1000); + assertThat(spins.get(), Matchers.lessThan(5L)); + } + finally + { + server.stop(); + } + } }