Repository: netty/netty
Issue: Memleak

### Expected behavior

### Actual behavior
![image](https://user-images.githubusercontent.com/20749545/115715628-e8c62680-a3aa-11eb-9373-e2dea504a1f6.png)
2021-04-22 19:17:28 805[ERROR][ResourceLeakDetector.java-319][lettuce-epollEventLoop-22-4]-LEAK: ByteBuf.release() was not called before it's garbage-collected. See https://netty.io/wiki/reference-counted-objects.html for more information.
Recent access records: 
#1:
	io.netty.buffer.AdvancedLeakAwareByteBuf.toString(AdvancedLeakAwareByteBuf.java:742)
	io.netty.handler.codec.http.multipart.MemoryAttribute.getValue(MemoryAttribute.java:65)
	io.vertx.core.http.impl.HttpServerRequestImpl.endDecode(HttpServerRequestImpl.java:535)
	io.vertx.core.http.impl.HttpServerRequestImpl.onEnd(HttpServerRequestImpl.java:517)
	io.vertx.core.http.impl.HttpServerRequestImpl.handleEnd(HttpServerRequestImpl.java:509)
	io.vertx.core.http.impl.Http1xServerConnection.handleEnd(Http1xServerConnection.java:176)
	io.vertx.core.http.impl.Http1xServerConnection.handleContent(Http1xServerConnection.java:163)
	io.vertx.core.http.impl.Http1xServerConnection.handleMessage(Http1xServerConnection.java:140)
	io.vertx.core.impl.ContextImpl.executeTask(ContextImpl.java:366)
	io.vertx.core.impl.EventLoopContext.execute(EventLoopContext.java:43)
	io.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:229)
	io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:163)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93)
	io.netty.handler.codec.http.websocketx.extensions.WebSocketServerExtensionHandler.channelRead(WebSocketServerExtensionHandler.java:102)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
	io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1533)
	io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1282)
	io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1329)
	io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508)
	io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447)
	io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
	io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
	io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
	io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
	io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
	io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
	io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	java.lang.Thread.run(Thread.java:748)
#2:
	io.netty.buffer.AdvancedLeakAwareByteBuf.writeByte(AdvancedLeakAwareByteBuf.java:544)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder$UrlDecoder.process(HttpPostStandardRequestDecoder.java:747)
	io.netty.buffer.AbstractByteBuf.forEachByteAsc0(AbstractByteBuf.java:1303)
	io.netty.buffer.CompositeByteBuf.forEachByteAsc0(CompositeByteBuf.java:678)
	io.netty.buffer.AbstractByteBuf.forEachByte(AbstractByteBuf.java:1283)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.decodeAttribute(HttpPostStandardRequestDecoder.java:666)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.setFinalBuffer(HttpPostStandardRequestDecoder.java:637)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.parseBodyAttributes(HttpPostStandardRequestDecoder.java:561)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.parseBody(HttpPostStandardRequestDecoder.java:375)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.offer(HttpPostStandardRequestDecoder.java:304)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.offer(HttpPostStandardRequestDecoder.java:49)
	io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.offer(HttpPostRequestDecoder.java:223)
	io.vertx.core.http.impl.HttpServerRequestImpl.onData(HttpServerRequestImpl.java:488)
	io.vertx.core.http.impl.HttpServerRequestImpl.handleContent(HttpServerRequestImpl.java:138)
	io.vertx.core.http.impl.Http1xServerConnection.handleContent(Http1xServerConnection.java:160)
	io.vertx.core.http.impl.Http1xServerConnection.handleMessage(Http1xServerConnection.java:140)
	io.vertx.core.impl.ContextImpl.executeTask(ContextImpl.java:366)
	io.vertx.core.impl.EventLoopContext.execute(EventLoopContext.java:43)
	io.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:229)
	io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:163)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93)
	io.netty.handler.codec.http.websocketx.extensions.WebSocketServerExtensionHandler.channelRead(WebSocketServerExtensionHandler.java:102)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
	io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1533)
	io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1282)
	io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1329)
	io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508)
	io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447)
	io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
	io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
	io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
	io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
	io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
	io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
	io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	java.lang.Thread.run(Thread.java:748)
#3:
	io.netty.buffer.AdvancedLeakAwareByteBuf.writeByte(AdvancedLeakAwareByteBuf.java:544)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder$UrlDecoder.process(HttpPostStandardRequestDecoder.java:755)
	io.netty.buffer.AbstractByteBuf.forEachByteAsc0(AbstractByteBuf.java:1303)
	io.netty.buffer.CompositeByteBuf.forEachByteAsc0(CompositeByteBuf.java:678)
	io.netty.buffer.AbstractByteBuf.forEachByte(AbstractByteBuf.java:1283)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.decodeAttribute(HttpPostStandardRequestDecoder.java:666)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.setFinalBuffer(HttpPostStandardRequestDecoder.java:637)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.parseBodyAttributes(HttpPostStandardRequestDecoder.java:561)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.parseBody(HttpPostStandardRequestDecoder.java:375)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.offer(HttpPostStandardRequestDecoder.java:304)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.offer(HttpPostStandardRequestDecoder.java:49)
	io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.offer(HttpPostRequestDecoder.java:223)
	io.vertx.core.http.impl.HttpServerRequestImpl.onData(HttpServerRequestImpl.java:488)
	io.vertx.core.http.impl.HttpServerRequestImpl.handleContent(HttpServerRequestImpl.java:138)
	io.vertx.core.http.impl.Http1xServerConnection.handleContent(Http1xServerConnection.java:160)
	io.vertx.core.http.impl.Http1xServerConnection.handleMessage(Http1xServerConnection.java:140)
	io.vertx.core.impl.ContextImpl.executeTask(ContextImpl.java:366)
	io.vertx.core.impl.EventLoopContext.execute(EventLoopContext.java:43)
	io.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:229)
	io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:163)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93)
	io.netty.handler.codec.http.websocketx.extensions.WebSocketServerExtensionHandler.channelRead(WebSocketServerExtensionHandler.java:102)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
	io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1533)
	io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1282)
	io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1329)
	io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508)
	io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447)
	io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
	io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
	io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
	io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
	io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
	io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
	io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	java.lang.Thread.run(Thread.java:748)
Created at:
	io.netty.buffer.UnpooledByteBufAllocator.newDirectBuffer(UnpooledByteBufAllocator.java:96)
	io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:187)
	io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:178)
	io.netty.buffer.AbstractByteBufAllocator.buffer(AbstractByteBufAllocator.java:115)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.decodeAttribute(HttpPostStandardRequestDecoder.java:664)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.setFinalBuffer(HttpPostStandardRequestDecoder.java:637)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.parseBodyAttributes(HttpPostStandardRequestDecoder.java:561)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.parseBody(HttpPostStandardRequestDecoder.java:375)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.offer(HttpPostStandardRequestDecoder.java:304)
	io.netty.handler.codec.http.multipart.HttpPostStandardRequestDecoder.offer(HttpPostStandardRequestDecoder.java:49)
	io.netty.handler.codec.http.multipart.HttpPostRequestDecoder.offer(HttpPostRequestDecoder.java:223)
	io.vertx.core.http.impl.HttpServerRequestImpl.onData(HttpServerRequestImpl.java:488)
	io.vertx.core.http.impl.HttpServerRequestImpl.handleContent(HttpServerRequestImpl.java:138)
	io.vertx.core.http.impl.Http1xServerConnection.handleContent(Http1xServerConnection.java:160)
	io.vertx.core.http.impl.Http1xServerConnection.handleMessage(Http1xServerConnection.java:140)
	io.vertx.core.impl.ContextImpl.executeTask(ContextImpl.java:366)
	io.vertx.core.impl.EventLoopContext.execute(EventLoopContext.java:43)
	io.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:229)
	io.vertx.core.net.impl.VertxHandler.channelRead(VertxHandler.java:163)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.channel.ChannelInboundHandlerAdapter.channelRead(ChannelInboundHandlerAdapter.java:93)
	io.netty.handler.codec.http.websocketx.extensions.WebSocketServerExtensionHandler.channelRead(WebSocketServerExtensionHandler.java:102)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
	io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1533)
	io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1282)
	io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1329)
	io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508)
	io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447)
	io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
	io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
	io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
	io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
	io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
	io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
	io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
	io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
	io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
	io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
	io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	java.lang.Thread.run(Thread.java:748)
### Steps to reproduce

### Minimal yet complete reproducer code (or URL to code)

### Netty version
4.1.59Final
### JVM version (e.g. `java -version`)
openjdk version "1.8.0_262"
### OS version (e.g. `uname -a`)
Linux host-10-33-176-104 4.18.0-147.5.1.2.h340.eulerosv2r9.x86_64 #1 SMP Sat Jan 30 09:00:44 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

Issue comments:
Related to #11174 

A fix will be proposed soon


Pull request review comments:
@fredericBregier can you do this change in a separate PR and also add a unit test ?
@normanmaurer I'm not sure I can. Let me explain.
First, this is already in place in HttpPostStandardRequestDecoder, so it should be also within Multipart too.

I notice this during PR since the deploy was wrong due to some Junit having a Leak detection error due to this missing.

So, in fact, there are already tests for that, but relying on leak detection step in CI/CD.

For Multipart, such as: 
- testMultipartRequestWithFileInvalidCharset
- testMultipartRequestWithFieldInvalidCharset
- testDecodeMalformedNotEncodedContentDispositionFieldParameters
- testDecodeMalformedBadCharsetContentDispositionFieldParameters

While on Standard one, we have:
- testNotLeak
- testNotLeakDirectBufferWhenWrapIllegalArgumentException
- testNotLeakWhenWrapIllegalArgumentException
- testDecodeFullHttpRequestWithUrlEncodedBodyWithBrokenHexByte0
- testDecodeFullHttpRequestWithUrlEncodedBodyWithBrokenHexByte1
- testDecodeFullHttpRequestWithUrlEncodedBodyWithInvalidHexNibbleHi
- testDecodeFullHttpRequestWithUrlEncodedBodyWithInvalidHexNibbleLo

They all share the same spirit: allocating a Decoder with a wrong parameter, but request shall be released and as there is no Decoder, we cannot check it but the check on memory leak i the CI/CD get them if they are not correctly handled.

If I removed this, it will certainly failed during leak detection, as it was the case before I added this, and with equal action than to the other standard implementation.

WDYT?
Sounds good.. But please just do it in a separate PR. This will make it easier to review / revert etc if needed. 
OK, I will remove it, but not sure it will not generate leak detetection errors on CI/CD then. 
And if is so, this PR could not be successful, we shall probably have both but in separate commit if you want. Let see what's happening when removing it.
As I suspected, removing this is causing leak detection.

This should have been done when the standard decoder was changed, but it wasn't. Now, it's necessary.
So how can we proceed?
All tests that goes to "Checking for detected leak" have the following similar output:

      Run ./.github/scripts/check_leak.sh build-leak.output
        ./.github/scripts/check_leak.sh build-leak.output
        shell: /usr/bin/bash -e {0}
      Leak detected, please inspect build log
      Error: Process completed with exit code 1.

I repushed the commit with the correction on constructor, as it should be and in line with the other one for Standard decoder. If you have any suggestion, I will go through them.
Reference of CI/CD was: https://github.com/netty/netty/pull/11188/checks?check_run_id=2440801961
I factored out this change in its own PR and added a unit test... please have a look https://github.com/netty/netty/pull/11207
OK, I will rebase once merged (review is OK ;-) )
Rebase done, CI/CD on going...
@fredericBregier can you explain me why this change ?
Several reasons:

- The decoder is not acting in the same way on every chunk : only the first one was `retainedSlice`
- This introduces some bad usages on user's end where the original buffer (from Chunk) were retained and released as soon as possible (the original Chunk), involving memory leak
- It simplifies a lot the mechanism, while it allocates a duplicate ByteBuf, it is as for the next chunks, and performances were not degraded, neither memory pressure (cf Flame on #11175 )

Patch that resolved the issue:
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java
index 5099ee60ac4..490b1ffcc14 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostMultipartRequestDecoder.java
@@ -43,7 +43,6 @@
 import java.util.Map;
 import java.util.TreeMap;
 
-import static io.netty.buffer.Unpooled.EMPTY_BUFFER;
 import static io.netty.util.internal.ObjectUtil.*;
 
 /**
@@ -336,13 +335,8 @@ public HttpPostMultipartRequestDecoder offer(HttpContent content) {
 
         ByteBuf buf = content.content();
         if (undecodedChunk == null) {
-            undecodedChunk = isLastChunk ?
-                    // Take a slice instead of copying when the first chunk is also the last
-                    // as undecodedChunk.writeBytes will never be called.
-                    buf.retainedSlice() :
-                    // Maybe we should better not copy here for performance reasons but this will need
-                    // more care by the caller to release the content in a correct manner later
-                    // So maybe something to optimize on a later stage
+            undecodedChunk =
+                    // Since the Handler will release the incoming later on, we need to copy it
                     //
                     // We are explicit allocate a buffer and NOT calling copy() as otherwise it may set a maxCapacity
                     // which is not really usable for us as we may exceed it once we add more bytes.
@@ -958,8 +952,15 @@ protected InterfaceHttpData getFileUpload(String delimiter) {
      */
     @Override
     public void destroy() {
-        // Release all data items, including those not yet pulled
+        // Release all data items, including those not yet pulled, only file based items
         cleanFiles();
+        // Clean Memory based data
+        for (InterfaceHttpData httpData : bodyListHttpData) {
+            // Might have been already released by the user
+            if (httpData.refCnt() > 0) {
+                httpData.release();
+            }
+        }
 
         destroyed = true;
 
diff --git a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java
index d2ef677dbf0..bdbccfa9f2f 100644
--- a/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java
+++ b/codec-http/src/main/java/io/netty/handler/codec/http/multipart/HttpPostStandardRequestDecoder.java
@@ -153,7 +153,7 @@ public HttpPostStandardRequestDecoder(HttpDataFactory factory, HttpRequest reque
         this.factory = checkNotNull(factory, "factory");
         try {
             if (request instanceof HttpContent) {
-                // Offer automatically if the given request is als type of HttpContent
+                // Offer automatically if the given request is as type of HttpContent
                 // See #1089
                 offer((HttpContent) request);
             } else {
@@ -287,13 +287,8 @@ public HttpPostStandardRequestDecoder offer(HttpContent content) {
 
         ByteBuf buf = content.content();
         if (undecodedChunk == null) {
-            undecodedChunk = isLastChunk ?
-                    // Take a slice instead of copying when the first chunk is also the last
-                    // as undecodedChunk.writeBytes will never be called.
-                    buf.retainedSlice() :
-                    // Maybe we should better not copy here for performance reasons but this will need
-                    // more care by the caller to release the content in a correct manner later
-                    // So maybe something to optimize on a later stage.
+            undecodedChunk =
+                    // Since the Handler will release the incoming later on, we need to copy it
                     //
                     // We are explicit allocate a buffer and NOT calling copy() as otherwise it may set a maxCapacity
                     // which is not really usable for us as we may exceed it once we add more bytes.
@@ -693,8 +688,15 @@ private static ByteBuf decodeAttribute(ByteBuf b, Charset charset) {
      */
     @Override
     public void destroy() {
-        // Release all data items, including those not yet pulled
+        // Release all data items, including those not yet pulled, only file based items
         cleanFiles();
+        // Clean Memory based data
+        for (InterfaceHttpData httpData : bodyListHttpData) {
+            // Might have been already released by the user
+            if (httpData.refCnt() > 0) {
+                httpData.release();
+            }
+        }
 
         destroyed = true;
 


Test patch:
diff --git a/codec-http/src/test/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoderTest.java b/codec-http/src/test/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoderTest.java
index 40f2f400a4e..665606fad83 100644
--- a/codec-http/src/test/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoderTest.java
+++ b/codec-http/src/test/java/io/netty/handler/codec/http/multipart/HttpPostRequestDecoderTest.java
@@ -88,7 +88,8 @@ private static void testBinaryStreamUpload(boolean withSpace) throws Exception {
             // Create decoder instance to test.
             final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(inMemoryFactory, req);
 
-            decoder.offer(new DefaultHttpContent(Unpooled.copiedBuffer(body, CharsetUtil.UTF_8)));
+            ByteBuf buf = Unpooled.copiedBuffer(body, CharsetUtil.UTF_8);
+            decoder.offer(new DefaultHttpContent(buf));
             decoder.offer(new DefaultHttpContent(Unpooled.EMPTY_BUFFER));
 
             // Validate it's enough chunks to decode upload.
@@ -102,6 +103,7 @@ private static void testBinaryStreamUpload(boolean withSpace) throws Exception {
                     data, upload.getString(CharsetUtil.UTF_8));
             upload.release();
             decoder.destroy();
+            buf.release();
         }
     }
 
@@ -134,8 +136,8 @@ public void testFullHttpRequestUpload() throws Exception {
         // Create decoder instance to test.
         final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(inMemoryFactory, req);
         assertFalse(decoder.getBodyHttpDatas().isEmpty());
-        req.release();
         decoder.destroy();
+        assertTrue(req.release());
     }
 
     // See https://github.com/netty/netty/issues/2544
@@ -181,8 +183,8 @@ public void testMultipartCodecWithCRasEndOfAttribute() throws Exception {
             assertNotNull(datar);
             assertEquals(datas[i].getBytes(CharsetUtil.UTF_8).length, datar.length);
 
-            req.release();
             decoder.destroy();
+            assertTrue(req.release());
         }
     }
 
@@ -215,8 +217,8 @@ public void testQuotedBoundary() throws Exception {
         // Create decoder instance to test.
         final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(inMemoryFactory, req);
         assertFalse(decoder.getBodyHttpDatas().isEmpty());
-        req.release();
         decoder.destroy();
+        assertTrue(req.release());
     }
 
     // See https://github.com/netty/netty/issues/1848
@@ -276,6 +278,8 @@ public void testNoZeroOut() throws Exception {
 
         aDecodedData.release();
         aDecoder.destroy();
+        aSmallBuf.release();
+        aLargeBuf.release();
     }
 
     // See https://github.com/netty/netty/issues/2305
@@ -373,8 +377,8 @@ public void testFilenameContainingSemicolon() throws Exception {
         // Create decoder instance to test.
         final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(inMemoryFactory, req);
         assertFalse(decoder.getBodyHttpDatas().isEmpty());
-        req.release();
         decoder.destroy();
+        assertTrue(req.release());
     }
 
     @Test
@@ -403,8 +407,8 @@ public void testFilenameContainingSemicolon2() throws Exception {
         assertTrue(part1 instanceof FileUpload);
         FileUpload fileUpload = (FileUpload) part1;
         assertEquals("tmp 0.txt", fileUpload.getFilename());
-        req.release();
         decoder.destroy();
+        assertTrue(req.release());
     }
 
     @Test
@@ -434,8 +438,8 @@ public void testMultipartRequestWithoutContentTypeBody() {
         // Create decoder instance to test without any exception.
         final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(inMemoryFactory, req);
         assertFalse(decoder.getBodyHttpDatas().isEmpty());
-        req.release();
         decoder.destroy();
+        assertTrue(req.release());
     }
 
     @Test
@@ -467,8 +471,8 @@ public void testDecodeOtherMimeHeaderFields() throws Exception {
         FileUpload fileUpload = (FileUpload) part1;
         byte[] fileBytes = fileUpload.get();
         assertTrue("the filecontent should not be decoded", filecontent.equals(new String(fileBytes)));
-        req.release();
         decoder.destroy();
+        assertTrue(req.release());
     }
 
     @Test
@@ -497,7 +501,7 @@ public void testMultipartRequestWithFileInvalidCharset() throws Exception {
         } catch (HttpPostRequestDecoder.ErrorDataDecoderException e) {
             assertTrue(e.getCause() instanceof UnsupportedCharsetException);
         } finally {
-            req.release();
+            assertTrue(req.release());
         }
     }
 
@@ -530,7 +534,7 @@ public void testMultipartRequestWithFieldInvalidCharset() throws Exception {
         } catch (HttpPostRequestDecoder.ErrorDataDecoderException e) {
             assertTrue(e.getCause() instanceof UnsupportedCharsetException);
         } finally {
-            req.release();
+            assertTrue(req.release());
         }
     }
 
@@ -581,8 +585,8 @@ public void testDecodeContentDispositionFieldParameters() throws Exception {
         assertTrue("the item should be a FileUpload", part1 instanceof FileUpload);
         FileUpload fileUpload = (FileUpload) part1;
         assertEquals("the filename should be decoded", filename, fileUpload.getFilename());
-        req.release();
         decoder.destroy();
+        assertTrue(req.release());
     }
 
     // https://github.com/netty/netty/pull/7265
@@ -617,8 +621,8 @@ public void testDecodeWithLanguageContentDispositionFieldParameters() throws Exc
         assertTrue("the item should be a FileUpload", part1 instanceof FileUpload);
         FileUpload fileUpload = (FileUpload) part1;
         assertEquals("the filename should be decoded", filename, fileUpload.getFilename());
-        req.release();
         decoder.destroy();
+        assertTrue(req.release());
     }
 
     // https://github.com/netty/netty/pull/7265
@@ -649,7 +653,7 @@ public void testDecodeMalformedNotEncodedContentDispositionFieldParameters() thr
         } catch (HttpPostRequestDecoder.ErrorDataDecoderException e) {
             assertTrue(e.getCause() instanceof ArrayIndexOutOfBoundsException);
         } finally {
-            req.release();
+            assertTrue(req.release());
         }
     }
 
@@ -681,7 +685,7 @@ public void testDecodeMalformedBadCharsetContentDispositionFieldParameters() thr
         } catch (HttpPostRequestDecoder.ErrorDataDecoderException e) {
             assertTrue(e.getCause() instanceof UnsupportedCharsetException);
         } finally {
-            req.release();
+            assertTrue(req.release());
         }
     }
 
@@ -712,8 +716,8 @@ public void testDecodeMalformedEmptyContentTypeFieldParameters() throws Exceptio
         assertTrue(part1 instanceof FileUpload);
         FileUpload fileUpload = (FileUpload) part1;
         assertEquals("tmp-0.txt", fileUpload.getFilename());
-        req.release();
         decoder.destroy();
+        assertTrue(req.release());
     }
 
     // https://github.com/netty/netty/issues/8575
@@ -832,8 +836,8 @@ public void testDecodeWithLanguageContentDispositionFieldParametersForFix() thro
         FileUpload fileUpload = (FileUpload) part1;
         assertEquals("the filename should be decoded", filename, fileUpload.getFilename());
 
-        req.release();
         decoder.destroy();
+        assertTrue(req.release());
     }
 
     @Test
@@ -869,8 +873,8 @@ public void testDecodeFullHttpRequestWithUrlEncodedBody() throws Exception {
         assertTrue(attr.getByteBuf().isDirect());
         assertEquals("los angeles", attr.getValue());
 
-        req.release();
         decoder.destroy();
+        assertTrue(req.release());
     }
 
     @Test
@@ -987,7 +991,8 @@ private void commonTestBigFileDelimiterInMiddleChunk(HttpDataFactory factory, bo
         int bytesLastChunk = 10000;
         int fileSize = bytesPerChunk * nbChunks + bytesLastChunk; // set Xmx to a number lower than this and it crashes
 
-        String prefix = "--861fbeab-cd20-470c-9609-d40a0f704466\n" +
+        String delimiter = "--861fbeab-cd20-470c-9609-d40a0f704466";
+        String prefix = delimiter + "\n" +
                 "Content-Disposition: form-data; name=\"image\"; filename=\"guangzhou.jpeg\"\n" +
                 "Content-Type: image/jpeg\n" +
                 "Content-Length: " + fileSize + "\n" +
@@ -1003,8 +1008,10 @@ private void commonTestBigFileDelimiterInMiddleChunk(HttpDataFactory factory, bo
         request.headers().set("content-length", prefix.length() + fileSize + suffix.length());
 
         HttpPostMultipartRequestDecoder decoder = new HttpPostMultipartRequestDecoder(factory, request);
-        decoder.offer(new DefaultHttpContent(Unpooled.wrappedBuffer(prefix.getBytes(CharsetUtil.UTF_8))));
+        ByteBuf buf = Unpooled.wrappedBuffer(prefix.getBytes(CharsetUtil.UTF_8));
+        decoder.offer(new DefaultHttpContent(buf));
         assertNotNull(((HttpData) decoder.currentPartialHttpData()).content());
+        buf.release();
 
         byte[] body = new byte[bytesPerChunk];
         Arrays.fill(body, (byte) 1);
@@ -1020,11 +1027,16 @@ private void commonTestBigFileDelimiterInMiddleChunk(HttpDataFactory factory, bo
 
         byte[] bsuffix1 = suffix1.getBytes(CharsetUtil.UTF_8);
         byte[] previousLastbody = new byte[bytesLastChunk - bsuffix1.length];
+        byte[] bdelimiter = delimiter.getBytes(CharsetUtil.UTF_8);
         byte[] lastbody = new byte[2 * bsuffix1.length];
         Arrays.fill(previousLastbody, (byte) 1);
         previousLastbody[0] = HttpConstants.CR;
         previousLastbody[1] = HttpConstants.LF;
         Arrays.fill(lastbody, (byte) 1);
+        // put somewhere a not valid delimiter
+        for (int i = 0; i < bdelimiter.length; i++) {
+            previousLastbody[i + 10] = bdelimiter[i];
+        }
         lastbody[0] = HttpConstants.CR;
         lastbody[1] = HttpConstants.LF;
         for (int i = 0; i < bsuffix1.length; i++) {
@@ -1055,12 +1067,18 @@ private void commonTestBigFileDelimiterInMiddleChunk(HttpDataFactory factory, bo
         }
         assertTrue("Capacity should be less than 1M", decoder.getCurrentAllocatedCapacity()
                 < 1024 * 1024);
-        for (InterfaceHttpData httpData: decoder.getBodyHttpDatas()) {
-            httpData.release();
-            factory.removeHttpDataFromClean(request, httpData);
+        InterfaceHttpData[] httpDatas = decoder.getBodyHttpDatas().toArray(new InterfaceHttpData[0]);
+        for (InterfaceHttpData httpData : httpDatas) {
+            assertEquals("Before cleanAllHttpData should be 1", 1, httpData.refCnt());
         }
         factory.cleanAllHttpData();
+        for (InterfaceHttpData httpData : httpDatas) {
+            assertEquals("Before cleanAllHttpData should be 1 if in Memory", inMemory? 1 : 0, httpData.refCnt());
+        }
         decoder.destroy();
+        for (InterfaceHttpData httpData : httpDatas) {
+            assertEquals("RefCnt should be 0", 0, httpData.refCnt());
+        }
     }
 
     @Test
@@ -1121,7 +1139,9 @@ private void commonNotBadReleaseBuffersDuringDecoding(HttpDataFactory factory, b
             for (int i = 0; i < bp2.length; i++) {
                 prefix[bp1.length + 2 + i] = bp2[i];
             }
-            decoder.offer(new DefaultHttpContent(Unpooled.wrappedBuffer(prefix)));
+            ByteBuf buf = Unpooled.wrappedBuffer(prefix);
+            decoder.offer(new DefaultHttpContent(buf));
+            buf.release();
             byte[] body = new byte[bytesPerItem];
             Arrays.fill(body, (byte) rank);
             ByteBuf content = Unpooled.wrappedBuffer(body, 0, bytesPerItem);