diff --git a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2ConnectionHandler.java b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2ConnectionHandler.java index 909ca748ed..679078b587 100644 --- a/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2ConnectionHandler.java +++ b/codec-http2/src/main/java/io/netty/handler/codec/http2/Http2ConnectionHandler.java @@ -935,6 +935,7 @@ public class Http2ConnectionHandler extends ByteToMessageDecoder implements Http private final ChannelHandlerContext ctx; private final ChannelPromise promise; private final ScheduledFuture timeoutTask; + private boolean closed; ClosingChannelFutureListener(ChannelHandlerContext ctx, ChannelPromise promise) { this.ctx = ctx; @@ -963,6 +964,14 @@ public class Http2ConnectionHandler extends ByteToMessageDecoder implements Http } private void doClose() { + // We need to guard against multiple calls as the timeout may trigger close() first and then it will be + // triggered again because of operationComplete(...) is called. + if (closed) { + // This only happens if we also scheduled a timeout task. + assert timeoutTask != null; + return; + } + closed = true; if (promise == null) { ctx.close(); } else {