jonesdevelopment / sonar

Sonar is a lightweight, effective and easy-to-use anti-bot plugin for Velocity, BungeeCord, and Bukkit.
https://docs.jonesdev.xyz
GNU General Public License v3.0
118 stars 10 forks source link

Bug Report: Potential memory leak on BungeeCord #325

Closed jonesdevelopment closed 2 months ago

jonesdevelopment commented 2 months ago

General information

Sonar's custom decoder seems to leak a bit of memory on BungeeCord servers:

22:07:14 [SEVERE] LEAK: ByteBuf.release() was not called before it's garbage-collected. See https://netty.io/wiki/reference-counted-objects.html for more information.

This does not happen on Velocity proxies.

Steps to reproduce

  1. Start your BungeeCord proxy with the JVM arguments -Dio.netty.leakDetection.level=PARANOID

Sonar dump

/

Additional information

No response

FallenCrystal commented 2 months ago

Have you tried PacketWrapper#trySingleRelease in xyz.jonesdev.sonar.bungee.fallback.FallbackChannelHandler?

jonesdevelopment commented 2 months ago

Have you tried PacketWrapper#trySingleRelease in xyz.jonesdev.sonar.bungee.fallback.FallbackChannelHandler?

The releasing issue is already fixed. There's just one last weird error that is only thrown once — it's about the bandwidth handler (?)

FallenCrystal commented 2 months ago

The releasing issue is already fixed.

[io.netty.util.ResourceLeakDetector]: 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:
Created at:
        io.netty.buffer.PooledByteBufAllocator.newDirectBuffer(PooledByteBufAllocator.java:404)
        io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:188)
        io.netty.buffer.UnsafeByteBufUtil.copy(UnsafeByteBufUtil.java:454)
        io.netty.buffer.PooledUnsafeDirectByteBuf.copy(PooledUnsafeDirectByteBuf.java:216)
        io.netty.buffer.PooledSlicedByteBuf.copy(PooledSlicedByteBuf.java:101)
        io.netty.buffer.AbstractByteBuf.copy(AbstractByteBuf.java:1194)
        io.netty.buffer.WrappedByteBuf.copy(WrappedByteBuf.java:882)
        io.netty.buffer.AdvancedLeakAwareByteBuf.copy(AdvancedLeakAwareByteBuf.java:696)
        net.md_5.bungee.protocol.MinecraftDecoder.decode(MinecraftDecoder.java:43)
        net.md_5.bungee.protocol.MinecraftDecoder.decode(MinecraftDecoder.java:13)
        io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:88)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:346)
        io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:318)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        io.netty.handler.codec.ByteToMessageDecoder.handlerRemoved(ByteToMessageDecoder.java:266)
        io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:537)
        io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:469)
        io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:290)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:444)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:412)
        io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:440)
        io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:420)
        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:788)
        io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
        io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
        io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
        io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
        io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        java.base/java.lang.Thread.run(Thread.java:833)
jonesdevelopment commented 2 months ago

Sonar doesn't even appear in the stacktrace, so we can't even figure out what causes it.

FallenCrystal commented 2 months ago

If I'm not mistaken. You need to free byteBuf in PacketWrapper after hijacking the HandlerBoss. So I don't think it's risky to call PacketWrapper#trySingleRelease. And to a certain extent, it can solve the problem.

jonesdevelopment commented 2 months ago

If I'm not mistaken. You need to free byteBuf in PacketWrapper after hijacking the HandlerBoss. So I don't think it's risky to call trySingleRelease. And to a certain extent, it can solve the problem.

Feel free to open a PR since I have no idea how BungeeCord does their weird hack-y packet crap :(