netty: Allow handshakes to be interrupted by channel shutdown

If a handshake is ongoing during shutdown, this would substantially
reduce the time it takes to shut down. Previously, you would need to use
channel.shutdownNow() to have fast shutdown behavior, which is an
unnecessary use of the variant.

When the current approach was written WriteBufferingAndExceptionHandler
didn't exist and so it was hard to predict how the pipeline would react
to events (particularly because of HTTP/2 handler's re-definition of
close()). Now that WBAEH exists, this is more straight-forward.
This commit is contained in:
Eric Anderson 2020-12-02 17:01:05 -08:00 committed by Eric Anderson
parent 22d1af0c89
commit f2eb0af550
3 changed files with 6 additions and 4 deletions

View File

@ -767,7 +767,7 @@ class NettyClientHandler extends AbstractNettyHandler {
private void forcefulClose(final ChannelHandlerContext ctx, final ForcefulCloseCommand msg,
ChannelPromise promise) throws Exception {
// close() already called by NettyClientTransport, so just need to clean up streams
ctx.close();
connection().forEachActiveStream(new Http2StreamVisitor() {
@Override
public boolean visit(Http2Stream stream) throws Http2Exception {

View File

@ -346,9 +346,6 @@ class NettyClientTransport implements ConnectionClientTransport {
@Override
public void run() {
lifecycleManager.notifyShutdown(reason);
// Call close() directly since negotiation may not have completed, such that a write would
// be queued.
channel.close();
channel.write(new ForcefulCloseCommand(reason));
}
}, true);

View File

@ -124,6 +124,11 @@ final class WriteBufferingAndExceptionHandler extends ChannelDuplexHandler {
promise.setFailure(failCause);
ReferenceCountUtil.release(msg);
} else {
if (msg instanceof GracefulCloseCommand || msg instanceof ForcefulCloseCommand) {
// No point in continuing negotiation
ctx.close();
// Still enqueue the command in case the HTTP/2 handler is already on the pipeline
}
bufferedWrites.add(new ChannelWrite(msg, promise));
}
}