Skip to content

[BUG] ServerHangWatchdog Crash -疑似 ServerLoginMixin 导致主线程无限等待网络响应 | ServerHangWatchdog Crash - TrueUUID 1.0.5 blocks main thread (Netty await no timeout) #8

@system32ovo

Description

@system32ovo

TrueUUID 1.0.5 版本在 Minecraft 1.20.1 Forge 服务端中,通过ServerLoginMixin修改ServerLoginPacketListenerImpl的登录流程时,触发了主线程无限阻塞问题:
模组在onTick方法中调用sendDisconnectWithReason,并通过 Netty 的DefaultPromise.awaitUninterruptibly()等待客户端网络响应;
该方法未设置超时时间,当客户端失联(网络波动 / 强制关闭)时,主线程会无限等待,最终触发ServerHangWatchdog崩溃(单刻耗时超 60 秒);
问题与 CPU 算力、服务器负载无关(即使 CPU 有大量余量,主线程阻塞仍会导致崩溃)。
复现步骤 (To Reproduce)
环境:Minecraft 1.20.1 + Forge 47.4.13 + TrueUUID 1.0.5;
启动服务端,加载包含 TrueUUID 的模组列表;
玩家登录时触发 “断开连接” 逻辑(如 UUID 重复 / 网络波动 / 客户端强制关闭);
服务端主线程卡在awaitUninterruptibly(),60 秒后触发ServerHangWatchdog崩溃。
预期行为 (Expected behavior)
网络等待逻辑应设置超时时间,避免主线程无限阻塞;
登录流程的网络操作应改用异步线程处理,不阻塞Server thread;
即使客户端失联,服务端也不应触发单刻超时崩溃。
环境信息 (Environment)
Minecraft 版本:1.20.1
Forge 版本:47.4.13
TrueUUID 版本:1.0.5
操作系统:Linux amd64 (6.12.48+deb13-amd64)
Java 版本:21.0.2
服务器配置:AMD Ryzen 9 9950X (16 核 32 线程),JVM 最大堆内存 7G
关键报错日志 (Crash Log Snippets)

-- Head --
Thread: Server thread
Suspected Mod: 
	TrueUUID (trueuuid), Version: 1.0.5
		Mixin class: cn.alini.trueuuid.mixin.server.ServerLoginMixin
		Target: net.minecraft.server.network.ServerLoginPacketListenerImpl
Stacktrace:
	at net.minecraft.server.network.ServerLoginPacketListenerImpl.handler$bbn000$trueuuid$onTick(ServerLoginPacketListenerImpl.java:629)
	at net.minecraft.server.network.ServerLoginPacketListenerImpl.sendDisconnectWithReason(ServerLoginPacketListenerImpl.java:764)
	at io.netty.util.concurrent.DefaultPromise.awaitUninterruptibly(DefaultPromise.java:275)
Caused by: java.lang.Error: ServerHangWatchdog detected that a single server tick took 60.00 seconds (should be max 0.05)

补充说明 (Additional context)
该问题并非 “必现”,猜测仅在玩家登录触发断开连接逻辑且客户端失联时触发,概率极低,但确实会导致崩溃,麻烦检查下代码看看是不是这个问题;

····························································································································································
In version 1.0.5 of the TrueUUID mod running on a Minecraft 1.20.1 Forge server, modifying the login process of ServerLoginPacketListenerImpl via ServerLoginMixin triggers an indefinite main thread blocking issue:
The mod calls sendDisconnectWithReason in the onTick method and waits for the client's network response through Netty's DefaultPromise.awaitUninterruptibly();
This method has no timeout set. When the client is disconnected (e.g., network fluctuation / forced shutdown), the main thread waits indefinitely, eventually triggering a ServerHangWatchdog crash (a single server tick takes over 60 seconds);
The issue is unrelated to CPU computing power or server load (even with ample remaining CPU resources, main thread blocking still causes a crash).

Environment: Minecraft 1.20.1 + Forge 47.4.13 + TrueUUID 1.0.5;
Start the server with the mod list including TrueUUID;
Trigger the "disconnect" logic during player login (e.g., duplicate UUID / network fluctuation / client forced shutdown);
The server main thread gets stuck at awaitUninterruptibly(), and a ServerHangWatchdog crash is triggered after 60 seconds.

A timeout should be added to the network waiting logic to prevent indefinite main thread blocking;
Network operations in the login process should be handled by asynchronous threads instead of blocking the Server thread;
The server should not trigger a tick timeout crash even if the client is disconnected.

Environment
Minecraft Version: 1.20.1
Forge Version: 47.4.13
TrueUUID Version: 1.0.5
Operating System: Linux amd64 (6.12.48+deb13-amd64)
Java Version: 21.0.2
Server Configuration: AMD Ryzen 9 9950X (16 cores / 32 threads), JVM maximum heap memory 7G

Crash Log Snippets

-- Head --
Thread: Server thread
Suspected Mod: 
	TrueUUID (trueuuid), Version: 1.0.5
		Mixin class: cn.alini.trueuuid.mixin.server.ServerLoginMixin
		Target: net.minecraft.server.network.ServerLoginPacketListenerImpl
Stacktrace:
	at net.minecraft.server.network.ServerLoginPacketListenerImpl.handler$bbn000$trueuuid$onTick(ServerLoginPacketListenerImpl.java:629)
	at net.minecraft.server.network.ServerLoginPacketListenerImpl.sendDisconnectWithReason(ServerLoginPacketListenerImpl.java:764)
	at io.netty.util.concurrent.DefaultPromise.awaitUninterruptibly(DefaultPromise.java:275)
Caused by: java.lang.Error: ServerHangWatchdog detected that a single server tick took 60.00 seconds (should be max 0.05)

Additional context: This issue is not consistently reproducible — it is speculated to only occur when the disconnect logic is triggered during player login and the client is disconnected simultaneously. The occurrence probability is extremely low, but it does cause server crashes. Could you please check the code to confirm if this is the root cause?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions