Improved handling of asynchronous failures.
This commit is contained in:
parent
3359db09bb
commit
2dce90c98d
|
@ -40,6 +40,7 @@ import org.eclipse.jetty.server.Connector;
|
||||||
import org.eclipse.jetty.server.HttpChannel;
|
import org.eclipse.jetty.server.HttpChannel;
|
||||||
import org.eclipse.jetty.server.HttpConfiguration;
|
import org.eclipse.jetty.server.HttpConfiguration;
|
||||||
import org.eclipse.jetty.server.HttpInput;
|
import org.eclipse.jetty.server.HttpInput;
|
||||||
|
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||||
import org.eclipse.jetty.util.BufferUtil;
|
import org.eclipse.jetty.util.BufferUtil;
|
||||||
import org.eclipse.jetty.util.Callback;
|
import org.eclipse.jetty.util.Callback;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
@ -329,10 +330,18 @@ public class HttpChannelOverHTTP2 extends HttpChannel
|
||||||
{
|
{
|
||||||
getHttpTransport().onStreamFailure(failure);
|
getHttpTransport().onStreamFailure(failure);
|
||||||
if (onEarlyEOF())
|
if (onEarlyEOF())
|
||||||
handle();
|
{
|
||||||
|
ContextHandler handler = getState().getContextHandler();
|
||||||
|
if (handler != null)
|
||||||
|
handler.handle(getRequest(), this);
|
||||||
else
|
else
|
||||||
|
handle();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
getState().asyncError(failure);
|
getState().asyncError(failure);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void consumeInput()
|
protected void consumeInput()
|
||||||
{
|
{
|
||||||
|
|
|
@ -268,14 +268,17 @@ public class HttpTransportOverHTTP2 implements HttpTransport
|
||||||
{
|
{
|
||||||
private State state = State.IDLE;
|
private State state = State.IDLE;
|
||||||
private Callback callback;
|
private Callback callback;
|
||||||
|
private Throwable failure;
|
||||||
private boolean commit;
|
private boolean commit;
|
||||||
|
|
||||||
public boolean start(Callback callback, boolean commit)
|
public boolean start(Callback callback, boolean commit)
|
||||||
{
|
{
|
||||||
State state;
|
State state;
|
||||||
|
Throwable failure;
|
||||||
synchronized (this)
|
synchronized (this)
|
||||||
{
|
{
|
||||||
state = this.state;
|
state = this.state;
|
||||||
|
failure = this.failure;
|
||||||
if (state == State.IDLE)
|
if (state == State.IDLE)
|
||||||
{
|
{
|
||||||
this.state = State.WRITING;
|
this.state = State.WRITING;
|
||||||
|
@ -284,7 +287,9 @@ public class HttpTransportOverHTTP2 implements HttpTransport
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
callback.failed(new IllegalStateException("Invalid transport state: " + state));
|
if (failure == null)
|
||||||
|
failure = new IllegalStateException("Invalid transport state: " + state);
|
||||||
|
callback.failed(failure);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,32 +309,36 @@ public class HttpTransportOverHTTP2 implements HttpTransport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("HTTP2 Response #{}/{} {}",
|
LOG.debug("HTTP2 Response #{}/{} {} {}",
|
||||||
stream.getId(), Integer.toHexString(stream.getSession().hashCode()),
|
stream.getId(), Integer.toHexString(stream.getSession().hashCode()),
|
||||||
commit ? "committed" : "flushed content");
|
commit ? "commit" : "flush",
|
||||||
|
callback == null ? "failure" : "success");
|
||||||
if (callback != null)
|
if (callback != null)
|
||||||
callback.succeeded();
|
callback.succeeded();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void failed(Throwable x)
|
public void failed(Throwable failure)
|
||||||
{
|
{
|
||||||
boolean commit;
|
boolean commit;
|
||||||
Callback callback = null;
|
Callback callback = null;
|
||||||
synchronized (this)
|
synchronized (this)
|
||||||
{
|
{
|
||||||
commit = this.commit;
|
commit = this.commit;
|
||||||
|
// Only fail pending writes, as we
|
||||||
|
// may need to write an error page.
|
||||||
if (state == State.WRITING)
|
if (state == State.WRITING)
|
||||||
{
|
{
|
||||||
|
this.state = State.FAILED;
|
||||||
callback = this.callback;
|
callback = this.callback;
|
||||||
this.callback = null;
|
this.callback = null;
|
||||||
this.state = State.FAILED;
|
this.failure = failure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("HTTP2 Response #" + stream.getId() + " failed to " + (commit ? "commit" : "flush"), x);
|
LOG.debug(String.format("HTTP2 Response #%d/%h failed to %s", stream.getId(), stream.getSession(), commit ? "commit" : "flush"), failure);
|
||||||
if (callback != null)
|
if (callback != null)
|
||||||
callback.failed(x);
|
callback.failed(failure);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -340,7 +349,7 @@ public class HttpTransportOverHTTP2 implements HttpTransport
|
||||||
{
|
{
|
||||||
callback = this.callback;
|
callback = this.callback;
|
||||||
}
|
}
|
||||||
return callback.getInvocationType();
|
return callback != null ? callback.getInvocationType() : Callback.super.getInvocationType();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean onIdleTimeout(Throwable failure)
|
private boolean onIdleTimeout(Throwable failure)
|
||||||
|
@ -349,16 +358,19 @@ public class HttpTransportOverHTTP2 implements HttpTransport
|
||||||
Callback callback = null;
|
Callback callback = null;
|
||||||
synchronized (this)
|
synchronized (this)
|
||||||
{
|
{
|
||||||
|
// Ignore idle timeouts if not writing,
|
||||||
|
// as the application may be suspended.
|
||||||
result = state == State.WRITING;
|
result = state == State.WRITING;
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
|
this.state = State.TIMEOUT;
|
||||||
callback = this.callback;
|
callback = this.callback;
|
||||||
this.callback = null;
|
this.callback = null;
|
||||||
this.state = State.TIMEOUT;
|
this.failure = failure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("HTTP2 Response #" + stream.getId() + " idle timeout", failure);
|
LOG.debug(String.format("HTTP2 Response #%d/%h idle timeout", stream.getId(), stream.getSession()), failure);
|
||||||
if (result)
|
if (result)
|
||||||
callback.failed(failure);
|
callback.failed(failure);
|
||||||
return result;
|
return result;
|
||||||
|
|
Loading…
Reference in New Issue