Issue #354 (Spin loop in case of exception thrown during accept()).
Fixed by introducing an overridable method that performs an arbitrary sleep to avoid the spin loop. Subclasses may customize.
This commit is contained in:
parent
ef6d0194b9
commit
76689dd303
|
@ -528,6 +528,34 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
|
||||||
return getConnectionFactory(_defaultProtocol);
|
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 class Acceptor implements Runnable
|
||||||
{
|
{
|
||||||
private final int _id;
|
private final int _id;
|
||||||
|
@ -557,18 +585,20 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
Throwable exception = null;
|
||||||
while (isAccepting())
|
while (isAccepting())
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
accept(_id);
|
accept(_id);
|
||||||
|
exception = null;
|
||||||
}
|
}
|
||||||
catch (Throwable e)
|
catch (Throwable x)
|
||||||
{
|
{
|
||||||
if (isAccepting())
|
if (handleAcceptFailure(exception, x))
|
||||||
LOG.warn(e);
|
exception = x;
|
||||||
else
|
else
|
||||||
LOG.ignore(e);
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
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.server.handler.HandlerList;
|
||||||
import org.eclipse.jetty.toolchain.test.OS;
|
import org.eclipse.jetty.toolchain.test.OS;
|
||||||
import org.eclipse.jetty.util.IO;
|
import org.eclipse.jetty.util.IO;
|
||||||
|
import org.hamcrest.Matchers;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.anyOf;
|
import static org.hamcrest.Matchers.anyOf;
|
||||||
|
@ -235,4 +237,32 @@ public class ServerConnectorTest
|
||||||
assertEquals(2, connector.getBeans(ConnectionFactory.class).size());
|
assertEquals(2, connector.getBeans(ConnectionFactory.class).size());
|
||||||
assertEquals(proxy.getProtocol(), connector.getDefaultProtocol());
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue