diff --git a/handler/src/main/java/io/netty/handler/stream/ChunkedWriteHandler.java b/handler/src/main/java/io/netty/handler/stream/ChunkedWriteHandler.java index 617e84e569c0..7af75a6b2477 100644 --- a/handler/src/main/java/io/netty/handler/stream/ChunkedWriteHandler.java +++ b/handler/src/main/java/io/netty/handler/stream/ChunkedWriteHandler.java @@ -26,6 +26,7 @@ import io.netty.channel.ChannelProgressivePromise; import io.netty.channel.ChannelPromise; import io.netty.util.ReferenceCountUtil; +import io.netty.util.concurrent.Promise; import io.netty.util.internal.PendingWrite; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; @@ -214,6 +215,7 @@ private void doFlush(final ChannelHandlerContext ctx) throws Exception { } needsFlush = true; final PendingWrite currentWrite = this.currentWrite; + final Promise currentPromise = this.currentWrite.promise(); final Object pendingMessage = currentWrite.msg(); if (pendingMessage instanceof ChunkedInput) { @@ -281,7 +283,16 @@ public void run() { @Override public void operationComplete(ChannelFuture future) throws Exception { pendingWrites.decrementAndGet(); - currentWrite.successAndRecycle(); + if (future.isSuccess()) { + if (!currentPromise.isDone()) { + currentWrite.successAndRecycle(); + } + } else { + if (!currentPromise.isDone()) { + currentWrite.failAndRecycle(future.cause()); + } + } + closeInput(chunks); } }); @@ -292,7 +303,10 @@ public void operationComplete(ChannelFuture future) throws Exception { pendingWrites.decrementAndGet(); if (!future.isSuccess()) { closeInput((ChunkedInput) pendingMessage); - currentWrite.failAndRecycle(future.cause()); + if (!currentPromise.isDone()) { + // only recycle if not done before + currentWrite.failAndRecycle(future.cause()); + } } else { progress((ChannelPromise) currentWrite.promise()); } @@ -305,7 +319,10 @@ public void operationComplete(ChannelFuture future) throws Exception { pendingWrites.decrementAndGet(); if (!future.isSuccess()) { closeInput((ChunkedInput) pendingMessage); - currentWrite.failAndRecycle(future.cause()); + if (!currentPromise.isDone()) { + // only recycle if not done before + currentWrite.failAndRecycle(future.cause()); + } } else { progress((ChannelPromise) currentWrite.promise()); if (isWritable()) {