From e745ef0645cc63e017d0a6599610a59af22842f8 Mon Sep 17 00:00:00 2001 From: switchYello <1062641125@qq.com> Date: Mon, 21 Oct 2019 15:48:30 +0800 Subject: [PATCH] fix remove handler cause ByteToMessageDecoder out disorder (#9670) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Motivation: Data flowing in from the decoder flows out in sequence,Whether decoder removed or not. Modification: fire data in out and clear out when hander removed before call method handlerRemoved(ctx) Result: Fixes #9668 . --- .../handler/codec/ByteToMessageDecoder.java | 4 ++- .../codec/ByteToMessageDecoderTest.java | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java b/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java index 948a71d9a4..81ae3b2c75 100644 --- a/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java @@ -81,7 +81,7 @@ public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter try { final ByteBuf buffer; if (cumulation.writerIndex() > cumulation.maxCapacity() - in.readableBytes() - || cumulation.refCnt() > 1 || cumulation.isReadOnly()) { + || cumulation.refCnt() > 1 || cumulation.isReadOnly()) { // Expand cumulation (by replace it) when either there is not more room in the buffer // or if the refCnt is greater then 1 which may happen when the user use slice().retain() or // duplicate().retain() or if its read-only. @@ -505,6 +505,8 @@ public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter boolean removePending = decodeState == STATE_HANDLER_REMOVED_PENDING; decodeState = STATE_INIT; if (removePending) { + fireChannelRead(ctx, out, out.size()); + out.clear(); handlerRemoved(ctx); } } diff --git a/codec/src/test/java/io/netty/handler/codec/ByteToMessageDecoderTest.java b/codec/src/test/java/io/netty/handler/codec/ByteToMessageDecoderTest.java index 875de76662..cd9ee37083 100644 --- a/codec/src/test/java/io/netty/handler/codec/ByteToMessageDecoderTest.java +++ b/codec/src/test/java/io/netty/handler/codec/ByteToMessageDecoderTest.java @@ -399,4 +399,31 @@ public class ByteToMessageDecoderTest { } assertFalse(channel.finish()); } + + @Test + public void testDisorder() { + ByteToMessageDecoder decoder = new ByteToMessageDecoder() { + int count; + + //read 4 byte then remove this decoder + @Override + protected void decode(ChannelHandlerContext ctx, ByteBuf in, List out) { + out.add(in.readByte()); + if (++count >= 4) { + ctx.pipeline().remove(this); + } + } + }; + EmbeddedChannel channel = new EmbeddedChannel(decoder); + assertTrue(channel.writeInbound(Unpooled.wrappedBuffer(new byte[]{1, 2, 3, 4, 5}))); + assertEquals((byte) 1, channel.readInbound()); + assertEquals((byte) 2, channel.readInbound()); + assertEquals((byte) 3, channel.readInbound()); + assertEquals((byte) 4, channel.readInbound()); + ByteBuf buffer5 = channel.readInbound(); + assertEquals((byte) 5, buffer5.readByte()); + assertFalse(buffer5.isReadable()); + assertTrue(buffer5.release()); + assertFalse(channel.finish()); + } }