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
parent ffaf9cab65
commit a091d9df4e

View File

@ -915,6 +915,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;
@ -938,6 +939,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 {