Skip to content

Fixing LEAK: ByteBuf.release() when using circuit breaker with netty http producer#5273

Merged
davsclaus merged 1 commit into
apache:masterfrom
samratdhillon:feature/nettyProducerLeak
Mar 29, 2021
Merged

Fixing LEAK: ByteBuf.release() when using circuit breaker with netty http producer#5273
davsclaus merged 1 commit into
apache:masterfrom
samratdhillon:feature/nettyProducerLeak

Conversation

@samratdhillon
Copy link
Copy Markdown
Contributor

Fixes https://issues.apache.org/jira/browse/CAMEL-16418

LEAK: ByteBuf.release() results when using circuit breaker with netty http producer

Using circuit breaker pattern with camel netty http will result in memory leaks. Netty will report ByteBuff leak as noted in the below stack trace. This can be reproduced very easily with a simple route definition (code sample attached). Note that the leak has nothing to do with actual circuit breaker timeouts and will result irrespectively and every time the netty http producer is called. Also it occurs with implementation of camel-reslience4j and camel-microprofile

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:

#2:
io.netty.buffer.AdvancedLeakAwareCompositeByteBuf.retain(AdvancedLeakAwareCompositeByteBuf.java:36)
org.apache.camel.component.netty.http.NettyHttpProducer$NettyHttpProducerCallback.done(NettyHttpProducer.java:123)
org.apache.camel.component.netty.NettyProducer$NettyProducerCallback.done(NettyProducer.java:555)

org.apache.camel.component.netty.handlers.ClientChannelHandler.channelRead0(ClientChannelHandler.java:229)
io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
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.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
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.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
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.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:296)
io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
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)
java.base/java.lang.Thread.run(Thread.java:834)

…hese objects have onCompletion added by NettyHttpProducer. Otherwise original exchange objects will not have these SynchronizationAdapters set and will result in memory leak from NettyHttpProducer
@samratdhillon
Copy link
Copy Markdown
Contributor Author

samratdhillon commented Mar 28, 2021

Sample to reproduce the problem

`public class CamelRoute extends RouteBuilder{
@OverRide
public void configure() throws Exception {

    restConfiguration()
    .component("netty-http")
    .host("0.0.0.0")
    .port(8081)
    .bindingMode(RestBindingMode.json);

    rest().get("/demo").produces("text/plain").route()
    .transform()
    .constant("demo page");

    rest().get("/demo/get").route()
    .circuitBreaker()
    .resilience4jConfiguration().timeoutEnabled(true).timeoutDuration(10000)
    .end()
    .log(LoggingLevel.INFO, "incoming request")
    .to("rest:get:demo?host=localhost:8081")
    .onFallback().transform().constant("timeout")
    .end();
}

}`

@davsclaus davsclaus merged commit 9675f4b into apache:master Mar 29, 2021
@davsclaus
Copy link
Copy Markdown
Contributor

If you want to help backport this to 3.7.x, then you should take the commits from master branch and adjust the merge conflict and submit a new PR against the 3.7.x branch

@samratdhillon
Copy link
Copy Markdown
Contributor Author

@davsclaus PR #5274 has been created which backports this fix into 3.7.x

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants