From 5edb7083b64e1bfbf12dc4430cb80d3fd5739af1 Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Tue, 9 Dec 2014 18:16:55 +0900 Subject: [PATCH] Call ctx.flush() at least once in ChunkedWriteHandler.flush() Related: #3219 Motivation: ChunkedWriteHandler.flush() does not call ctx.flush() when channel is not writable. This can be a problem when other handler / non-Netty thread writes messages simultaneously, because ChunkedWriteHandler.flush() might have no chance to observe channel.isWritable() returns true and thus the channel is never flushed. Modifications: - Ensure that ChunkedWriteHandler.flush() calls ctx.flush() at least once. Result: A stall connection issue, that occurs when certain combination of handlers exist in a pipeline, has been fixed. (e.g. SslHandler and ChunkedWriteHandler) --- .../handler/stream/ChunkedWriteHandler.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) 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 72442ac1be..abe78bfc25 100644 --- a/handler/src/main/java/io/netty/handler/stream/ChunkedWriteHandler.java +++ b/handler/src/main/java/io/netty/handler/stream/ChunkedWriteHandler.java @@ -15,8 +15,6 @@ */ package io.netty.handler.stream; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.ByteBufHolder; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelDuplexHandler; @@ -136,16 +134,16 @@ public class ChunkedWriteHandler @Override public void flush(ChannelHandlerContext ctx) throws Exception { - Channel channel = ctx.channel(); - if (channel.isWritable() || !channel.isActive()) { - doFlush(ctx); + if (!doFlush(ctx)) { + // Make sure to flush at least once. + ctx.flush(); } } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { doFlush(ctx); - super.channelInactive(ctx); + ctx.fireChannelInactive(); } @Override @@ -197,12 +195,14 @@ public class ChunkedWriteHandler } } - private void doFlush(final ChannelHandlerContext ctx) throws Exception { + private boolean doFlush(final ChannelHandlerContext ctx) throws Exception { final Channel channel = ctx.channel(); if (!channel.isActive()) { discard(null); - return; + return false; } + + boolean flushed = false; while (channel.isWritable()) { if (currentWrite == null) { currentWrite = queue.poll(); @@ -307,12 +307,15 @@ public class ChunkedWriteHandler // Always need to flush ctx.flush(); + flushed = true; if (!channel.isActive()) { discard(new ClosedChannelException()); - return; + break; } } + + return flushed; } static void closeInput(ChunkedInput chunks) {