HTTP2: Guard against multiple ctx.close(...) calls with the same ChannelPromise (#10201)

Motivation:

Http2ConnectionHandler may call ctx.close(...) with the same promise instance multiple times if the timeout for gracefulShutdown elapse and the listener itself is notified. This can cause problems as other handlers in the pipeline may queue these promises and try to notify these later via setSuccess() or setFailure(...) which will then throw an IllegalStateException if the promise was notified already

Modification:

- Add boolean flag to ensure doClose() will only try to call ctx.close(...) one time

Result:

Don't call ctx.close(...) with the same promise multiple times when gradefulShutdown timeout elapses.
This commit is contained in:
Norman Maurer 2020-04-23 11:25:39 +02:00 committed by GitHub
parent 9c5008b109
commit 0cf919c389
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -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 {