CodecOutputList should be recycled in a finally block (#10186)

Motivation:

To ensure we always recycle the CodecOutputList we should better do it in a finally block

Modifications:

Call CodecOutputList.recycle() in finally

Result:

Less chances of non-recycled lists. Related to https://github.com/netty/netty/issues/10183
This commit is contained in:
Norman Maurer 2020-04-15 09:08:19 +02:00 committed by GitHub
parent 1b3e1985b4
commit 4c9d7492fb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 32 deletions

View File

@ -279,11 +279,12 @@ public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter
} catch (Exception e) { } catch (Exception e) {
throw new DecoderException(e); throw new DecoderException(e);
} finally { } finally {
try {
if (cumulation != null && !cumulation.isReadable()) { if (cumulation != null && !cumulation.isReadable()) {
numReads = 0; numReads = 0;
cumulation.release(); cumulation.release();
cumulation = null; cumulation = null;
} else if (++ numReads >= discardAfterReads) { } else if (++numReads >= discardAfterReads) {
// We did enough reads already try to discard some bytes so we not risk to see a OOME. // We did enough reads already try to discard some bytes so we not risk to see a OOME.
// See https://github.com/netty/netty/issues/4275 // See https://github.com/netty/netty/issues/4275
numReads = 0; numReads = 0;
@ -293,8 +294,10 @@ public abstract class ByteToMessageDecoder extends ChannelInboundHandlerAdapter
int size = out.size(); int size = out.size();
firedChannelRead |= out.insertSinceRecycled(); firedChannelRead |= out.insertSinceRecycled();
fireChannelRead(ctx, out, size); fireChannelRead(ctx, out, size);
} finally {
out.recycle(); out.recycle();
} }
}
} else { } else {
ctx.fireChannelRead(msg); ctx.fireChannelRead(msg);
} }

View File

@ -97,13 +97,16 @@ public abstract class MessageToMessageDecoder<I> extends ChannelInboundHandlerAd
} catch (Exception e) { } catch (Exception e) {
throw new DecoderException(e); throw new DecoderException(e);
} finally { } finally {
try {
int size = out.size(); int size = out.size();
for (int i = 0; i < size; i ++) { for (int i = 0; i < size; i++) {
ctx.fireChannelRead(out.getUnsafe(i)); ctx.fireChannelRead(out.getUnsafe(i));
} }
} finally {
out.recycle(); out.recycle();
} }
} }
}
/** /**
* Decode from one message to an other. This method will be called for each written message that can be handled * Decode from one message to an other. This method will be called for each written message that can be handled

View File

@ -92,9 +92,6 @@ public abstract class MessageToMessageEncoder<I> extends ChannelOutboundHandlerA
} }
if (out.isEmpty()) { if (out.isEmpty()) {
out.recycle();
out = null;
throw new EncoderException( throw new EncoderException(
StringUtil.simpleClassName(this) + " must produce at least one message."); StringUtil.simpleClassName(this) + " must produce at least one message.");
} }
@ -107,6 +104,7 @@ public abstract class MessageToMessageEncoder<I> extends ChannelOutboundHandlerA
throw new EncoderException(t); throw new EncoderException(t);
} finally { } finally {
if (out != null) { if (out != null) {
try {
final int sizeMinusOne = out.size() - 1; final int sizeMinusOne = out.size() - 1;
if (sizeMinusOne == 0) { if (sizeMinusOne == 0) {
ctx.write(out.getUnsafe(0), promise); ctx.write(out.getUnsafe(0), promise);
@ -119,10 +117,12 @@ public abstract class MessageToMessageEncoder<I> extends ChannelOutboundHandlerA
writePromiseCombiner(ctx, out, promise); writePromiseCombiner(ctx, out, promise);
} }
} }
} finally {
out.recycle(); out.recycle();
} }
} }
} }
}
private static void writeVoidPromise(ChannelHandlerContext ctx, CodecOutputList out) { private static void writeVoidPromise(ChannelHandlerContext ctx, CodecOutputList out) {
final ChannelPromise voidPromise = ctx.voidPromise(); final ChannelPromise voidPromise = ctx.voidPromise();