Mojira Archive
MC-121884

Server->Client custom payload packets can leak resources

Custom data packets have a PacketBuffer containing the data payload. While client->server packets release this buffer after the packet has been handled, server->client packets generally do not. (Compare processPacket for CPacketCustomPayload and SPacketCustomPayload)

Strangely, the buffer can actually be released in NetHandlerPlayClient#handleCustomPayload, but only for "MC|TrList" packets.

Putting the call to release in processPacket and removing the current "MC|TrList" special case seems like the best solution here.

Here's a log extract from a detected leak: (seen on a decompiled client connecting to a local server in offline mode, passing -Dio.netty.leakDetection.level=PARANOID to client VM args)

Nov 12, 2017 2:34:18 AM io.netty.util.ResourceLeakDetector reportTracedLeak
SEVERE: LEAK: ByteBuf.release() was not called before it's garbage-collected. See http://netty.io/wiki/reference-counted-objects.html for more information.
Recent access records: 3
#3:
	io.netty.buffer.AdvancedLeakAwareByteBuf.toString(AdvancedLeakAwareByteBuf.java:744)
	net.minecraft.network.PacketBuffer.toString(PacketBuffer.java:1289)
	net.minecraft.network.PacketBuffer.readString(PacketBuffer.java:380)
	net.minecraft.client.network.NetHandlerPlayClient.handleCustomPayload(NetHandlerPlayClient.java:1864)
	net.minecraft.network.play.server.SPacketCustomPayload.processPacket(SPacketCustomPayload.java:54)
	net.minecraft.network.play.server.SPacketCustomPayload.processPacket(SPacketCustomPayload.java:11)
	net.minecraft.network.PacketThreadUtil$1.run(PacketThreadUtil.java:15)
	java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	java.util.concurrent.FutureTask.run(FutureTask.java:266)
	net.minecraft.util.Util.runTask(Util.java:50)
	net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1068)
	net.minecraft.client.Minecraft.run(Minecraft.java:398)
	net.minecraft.client.main.Main.main(Main.java:118)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	java.lang.reflect.Method.invoke(Method.java:498)
	net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97)
	GradleStart.main(GradleStart.java:26)
#2:
	io.netty.buffer.AdvancedLeakAwareByteBuf.readByte(AdvancedLeakAwareByteBuf.java:396)
	net.minecraft.network.PacketBuffer.readByte(PacketBuffer.java:864)
	net.minecraft.network.PacketBuffer.readVarInt(PacketBuffer.java:201)
	net.minecraft.network.PacketBuffer.readString(PacketBuffer.java:368)
	net.minecraft.client.network.NetHandlerPlayClient.handleCustomPayload(NetHandlerPlayClient.java:1864)
	net.minecraft.network.play.server.SPacketCustomPayload.processPacket(SPacketCustomPayload.java:54)
	net.minecraft.network.play.server.SPacketCustomPayload.processPacket(SPacketCustomPayload.java:11)
	net.minecraft.network.PacketThreadUtil$1.run(PacketThreadUtil.java:15)
	java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	java.util.concurrent.FutureTask.run(FutureTask.java:266)
	net.minecraft.util.Util.runTask(Util.java:50)
	net.minecraft.client.Minecraft.runGameLoop(Minecraft.java:1068)
	net.minecraft.client.Minecraft.run(Minecraft.java:398)
	net.minecraft.client.main.Main.main(Main.java:118)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	java.lang.reflect.Method.invoke(Method.java:498)
	net.minecraftforge.gradle.GradleStartCommon.launch(GradleStartCommon.java:97)
	GradleStart.main(GradleStart.java:26)
#1:
	io.netty.buffer.AdvancedLeakAwareByteBuf.writeBytes(AdvancedLeakAwareByteBuf.java:600)
	io.netty.buffer.AbstractByteBuf.readBytes(AbstractByteBuf.java:829)
	io.netty.buffer.WrappedByteBuf.readBytes(WrappedByteBuf.java:616)
	io.netty.buffer.AdvancedLeakAwareByteBuf.readBytes(AdvancedLeakAwareByteBuf.java:469)
	net.minecraft.network.PacketBuffer.readBytes(PacketBuffer.java:959)
	net.minecraft.network.play.server.SPacketCustomPayload.readPacketData(SPacketCustomPayload.java:38)
	net.minecraft.network.NettyPacketDecoder.decode(NettyPacketDecoder.java:38)
	io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:411)
	io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:248)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)
	io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)
	io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:280)
	io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:396)
	io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:248)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:287)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1334)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:926)
	io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:134)
	io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:624)
	io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:559)
	io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:476)
	io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:438)
	io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
	java.lang.Thread.run(Thread.java:748)
Created at:
	io.netty.util.ResourceLeakDetector.track(ResourceLeakDetector.java:237)
	io.netty.buffer.PooledByteBufAllocator.newDirectBuffer(PooledByteBufAllocator.java:327)
	io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:181)
	io.netty.buffer.AbstractByteBufAllocator.buffer(AbstractByteBufAllocator.java:117)
	io.netty.buffer.AbstractByteBuf.readBytes(AbstractByteBuf.java:828)
	io.netty.buffer.WrappedByteBuf.readBytes(WrappedByteBuf.java:616)
	io.netty.buffer.AdvancedLeakAwareByteBuf.readBytes(AdvancedLeakAwareByteBuf.java:469)
	net.minecraft.network.PacketBuffer.readBytes(PacketBuffer.java:959)
	net.minecraft.network.play.server.SPacketCustomPayload.readPacketData(SPacketCustomPayload.java:38)
	net.minecraft.network.NettyPacketDecoder.decode(NettyPacketDecoder.java:38)
	io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:411)
	io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:248)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)
	io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:267)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:293)
	io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:280)
	io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:396)
	io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:248)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:287)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
	io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1334)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
	io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
	io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:926)
	io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:134)
	io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:624)
	io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:559)
	io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:476)
	io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:438)
	io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
	java.lang.Thread.run(Thread.java:748)

Fixed

Ben Staddon

2017-11-12, 04:52 AM

2024-02-04, 06:24 PM

2024-02-04, 06:24 PM

15

8

Confirmed

memory-leak

Minecraft 1.12.2 - 22w16bMinecraft 1.12.2, Minecraft 17w45b, Minecraft 17w46a, Minecraft 1.14.1, Minecraft 1.14.2 Pre-Release 2, 1.15 Pre-Release 2, 1.17.1, 1.18.2, 22w16b

Minecraft 18w01a, 23w31a