Issue #1759 - HTTP/2 producer can block in onReset.
Now both failures and timeouts, when they must call the application, do so by dispatching a Runnable to avoid to block the caller thread.
This commit is contained in:
parent
f7925aebd2
commit
154824049b
|
@ -156,7 +156,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
public boolean onStreamTimeout(IStream stream, Throwable failure)
|
||||
{
|
||||
HttpChannelOverHTTP2 channel = (HttpChannelOverHTTP2)stream.getAttribute(IStream.CHANNEL_ATTRIBUTE);
|
||||
boolean result = channel != null && channel.onStreamTimeout(failure);
|
||||
boolean result = channel != null && channel.onStreamTimeout(failure, task -> offerTask(task, true));
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} idle timeout on {}: {}", result ? "Processed" : "Ignored", stream, failure);
|
||||
return result;
|
||||
|
@ -168,7 +168,11 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
LOG.debug("Processing failure on {}: {}", stream, failure);
|
||||
HttpChannelOverHTTP2 channel = (HttpChannelOverHTTP2)stream.getAttribute(IStream.CHANNEL_ATTRIBUTE);
|
||||
if (channel != null)
|
||||
channel.onFailure(failure);
|
||||
{
|
||||
Runnable task = channel.onFailure(failure);
|
||||
if (task != null)
|
||||
offerTask(task, true);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean onSessionTimeout(Throwable failure)
|
||||
|
@ -179,7 +183,7 @@ public class HTTP2ServerConnection extends HTTP2Connection implements Connection
|
|||
{
|
||||
HttpChannelOverHTTP2 channel = (HttpChannelOverHTTP2)stream.getAttribute(IStream.CHANNEL_ATTRIBUTE);
|
||||
if (channel != null)
|
||||
result &= !channel.isRequestExecuting();
|
||||
result &= channel.isRequestIdle();
|
||||
}
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("{} idle timeout on {}: {}", result ? "Processed" : "Ignored", session, failure);
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.http2.server;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.eclipse.jetty.http.BadMessageException;
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
|
@ -40,6 +41,7 @@ import org.eclipse.jetty.server.Connector;
|
|||
import org.eclipse.jetty.server.HttpChannel;
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpInput;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.Callback;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -277,32 +279,39 @@ public class HttpChannelOverHTTP2 extends HttpChannel
|
|||
return handle || wasDelayed ? this : null;
|
||||
}
|
||||
|
||||
public boolean isRequestExecuting()
|
||||
public boolean isRequestIdle()
|
||||
{
|
||||
return !getState().isIdle();
|
||||
return getState().isIdle();
|
||||
}
|
||||
|
||||
public boolean onStreamTimeout(Throwable failure)
|
||||
public boolean onStreamTimeout(Throwable failure, Consumer<Runnable> consumer)
|
||||
{
|
||||
boolean result = false;
|
||||
if (isRequestIdle())
|
||||
{
|
||||
consumeInput();
|
||||
result = true;
|
||||
}
|
||||
|
||||
getHttpTransport().onStreamTimeout(failure);
|
||||
if (getRequest().getHttpInput().onIdleTimeout(failure))
|
||||
handle();
|
||||
consumer.accept(this::handleWithContext);
|
||||
|
||||
if (isRequestExecuting())
|
||||
return false;
|
||||
|
||||
consumeInput();
|
||||
return true;
|
||||
return result;
|
||||
}
|
||||
|
||||
public void onFailure(Throwable failure)
|
||||
public Runnable onFailure(Throwable failure)
|
||||
{
|
||||
getHttpTransport().onStreamFailure(failure);
|
||||
if (getRequest().getHttpInput().failed(failure))
|
||||
handle();
|
||||
else
|
||||
getState().asyncError(failure);
|
||||
boolean handle = getRequest().getHttpInput().failed(failure);
|
||||
consumeInput();
|
||||
return () ->
|
||||
{
|
||||
if (handle)
|
||||
handleWithContext();
|
||||
else
|
||||
getState().asyncError(failure);
|
||||
};
|
||||
}
|
||||
|
||||
protected void consumeInput()
|
||||
|
@ -310,6 +319,15 @@ public class HttpChannelOverHTTP2 extends HttpChannel
|
|||
getRequest().getHttpInput().consumeAll();
|
||||
}
|
||||
|
||||
private void handleWithContext()
|
||||
{
|
||||
ContextHandler context = getState().getContextHandler();
|
||||
if (context != null)
|
||||
context.handle(getRequest(), this);
|
||||
else
|
||||
handle();
|
||||
}
|
||||
|
||||
/**
|
||||
* If the associated response has the Expect header set to 100 Continue,
|
||||
* then accessing the input stream indicates that the handler/servlet
|
||||
|
|
Loading…
Reference in New Issue