From 402537cab0b36135d5a89240cd83e809e56cbaad 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 | 2 ++ .../codec/ByteToMessageDecoderTest.java | 27 +++++++++++++++++++ 2 files changed, 29 insertions(+) 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 6014bca470..a0d734eb17 100644 --- a/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java @@ -499,6 +499,8 @@ public abstract class ByteToMessageDecoder extends ChannelHandlerAdapter impleme 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 85182d8ba2..04ea4e8ce8 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, (byte) channel.readInbound()); + assertEquals((byte) 2, (byte) channel.readInbound()); + assertEquals((byte) 3, (byte) channel.readInbound()); + assertEquals((byte) 4, (byte) channel.readInbound()); + ByteBuf buffer5 = channel.readInbound(); + assertEquals((byte) 5, buffer5.readByte()); + assertFalse(buffer5.isReadable()); + assertTrue(buffer5.release()); + assertFalse(channel.finish()); + } }