From cb9660f83d45ab439b4f4ba751131dcadb1913c2 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Sun, 6 Apr 2014 20:49:03 +0200 Subject: [PATCH] Allow the user to call slice().retain() or duplicate.retain() in his/her ByteToMessageDecoder.decode(...) method. Motivation: At the moment a user can not safetly call slice().retain() or duplicate.retain()in the ByteToMessageDecoder.decode(...) implementation without the risk to see coruption because we may call discardSomeReadBytes() to make room on the buffer once the handling is done. Modifications: Check for the refCnt() before call discardSomeReadBytes() and also check before call decode(...) to create a copy if needed. Result: The user can safetly call slice().retain() or duplicate.retain() in his/her ByteToMessageDecoder.decode(...) method. --- .../handler/codec/ByteToMessageDecoder.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) 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 dec65dfa4c..bd880f9748 100644 --- a/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java +++ b/codec/src/main/java/io/netty/handler/codec/ByteToMessageDecoder.java @@ -132,7 +132,15 @@ public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter if (first) { cumulation = data; } else { - if (cumulation.writerIndex() > cumulation.maxCapacity() - data.readableBytes()) { + if (cumulation.writerIndex() > cumulation.maxCapacity() - data.readableBytes() + || cumulation.refCnt() > 1) { + // 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(). + // + // See: + // - https://github.com/netty/netty/issues/2327 + // - https://github.com/netty/netty/issues/1764 expandCumulation(ctx, data.readableBytes()); } cumulation.writeBytes(data); @@ -170,9 +178,14 @@ public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - if (cumulation != null && !first) { + if (cumulation != null && !first && cumulation.refCnt() == 1) { // discard some bytes if possible to make more room in the - // buffer + // buffer but only if the refCnt == 1 as otherwise the user may have + // used slice().retain() or duplicate().retain(). + // + // See: + // - https://github.com/netty/netty/issues/2327 + // - https://github.com/netty/netty/issues/1764 cumulation.discardSomeReadBytes(); } if (decodeWasNull) {