diff --git a/patches/server/0015-Add-a-simple-watchdog-for-tick-regions.patch b/patches/server/0015-Add-a-simple-watchdog-for-tick-regions.patch new file mode 100644 index 0000000..44cb370 --- /dev/null +++ b/patches/server/0015-Add-a-simple-watchdog-for-tick-regions.patch @@ -0,0 +1,257 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: MrHua269 +Date: Sun, 10 Mar 2024 05:04:33 +0000 +Subject: [PATCH] Add a simple watchdog for tick regions + + +diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java b/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java +index fc3d332aa1c1d469cedfe2aaa7102dcd78e25642..1ae61bc6603dd3ac290e3ead20416f9c5b63ff02 100644 +--- a/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java ++++ b/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java +@@ -279,6 +279,7 @@ public final class RegionizedServer { + */ + + private void globalTick(final int tickCount) { ++ me.earthme.luminol.utils.LuminolWatchDog.globalRegionHeartBeat(); //Luminol + /* + if (false) { + io.papermc.paper.threadedregions.ThreadedTicketLevelPropagator.main(null); +diff --git a/src/main/java/io/papermc/paper/threadedregions/ThreadedRegionizer.java b/src/main/java/io/papermc/paper/threadedregions/ThreadedRegionizer.java +index 531aa50f2c84e13358e8918bb0c15ea3cd036cb5..fd0053369eb68f0fd596d8acfba4a5247ef8105a 100644 +--- a/src/main/java/io/papermc/paper/threadedregions/ThreadedRegionizer.java ++++ b/src/main/java/io/papermc/paper/threadedregions/ThreadedRegionizer.java +@@ -167,6 +167,8 @@ public final class ThreadedRegionizer globalRegionLastKeepalive = null; ++ private static final Map,Long>> otherTickRegionKeepalive = Maps.newHashMap(); ++ private static final Executor checkTimer = CompletableFuture.delayedExecutor(50, TimeUnit.MILLISECONDS); ++ private static final Logger logger = MinecraftServer.LOGGER; ++ private static int tickCount = 0; ++ private static boolean runScheduleNext = true; ++ ++ public static void boot(){ ++ runCheck(); ++ } ++ ++ private static void scheduleCheck(){ ++ checkTimer.execute(LuminolWatchDog::runCheck); ++ } ++ ++ private static void runCheck(){ ++ try { ++ if (MinecraftServer.getServer().isStopped() || !runScheduleNext){ ++ return; ++ } ++ ++ tickCount++; ++ ++ final List> threadsToWarn = new ArrayList<>(); ++ final long currentTimeNano = System.nanoTime(); ++ boolean shouldStopServer = false; ++ ++ synchronized (keepaliveDataLock){ ++ if (globalRegionLastKeepalive != null){ ++ final Thread lastGlobalRegionThread = globalRegionLastKeepalive.getLeft(); ++ final long lastTicked = globalRegionLastKeepalive.getRight(); ++ ++ final long timeEscaped = currentTimeNano - lastTicked; ++ ++ if (timeEscaped >= WatchdogConfig.warnPeriodTicks * 50 * 1000 * 1000){ ++ threadsToWarn.add(Pair.of(lastGlobalRegionThread,timeEscaped)); ++ } ++ } ++ ++ for(Pair warnInfo : threadsToWarn){ ++ final Thread targetThread = warnInfo.getLeft(); ++ final long timeEscaped = warnInfo.getRight(); ++ ++ final ThreadedRegionizer.ThreadedRegion targetRegion; ++ ++ synchronized (keepaliveDataLock){ ++ targetRegion = otherTickRegionKeepalive.get(targetThread).getLeft(); ++ } ++ ++ if (tickCount % WatchdogConfig.warnPeriodTicks == 0){ ++ dumpSingleRegion(targetThread,targetRegion,timeEscaped); ++ } ++ ++ if (timeEscaped > WatchdogConfig.timeOutTicks * 50 * 1000 * 1000){ ++ shouldStopServer = true; ++ runScheduleNext = false; ++ } ++ } ++ ++ if (shouldStopServer){ ++ MinecraftServer.getServer().stopServer(); ++ } ++ } ++ }finally { ++ if (runScheduleNext){ ++ scheduleCheck(); ++ } ++ } ++ } ++ ++ private static void dumpSingleRegion(@NotNull Thread thread, @Nullable ThreadedRegionizer.ThreadedRegion region,long timeEscaped){ ++ final StringBuilder messageBuilder = new StringBuilder(); ++ messageBuilder.append("====================================").append("\n"); ++ messageBuilder.append("There is a single region that has no responding in " + TimeUnit.NANOSECONDS.toSeconds(timeEscaped) + " seconds!").append("\n"); ++ messageBuilder.append("If you believe this is a bug,please send it to github issue after checking your plugins!").append("\n"); ++ messageBuilder.append("Tick Region: ").append(region == null ? "Global Region" : "ChunkX(Center): " + region.getCenterChunk().x + " ChunkZ(Center): " + region.getCenterChunk().z).append("\n"); ++ messageBuilder.append("Thread Name: ").append(thread.getName()).append("\n"); ++ messageBuilder.append("Thread Id: ").append(thread.getId()).append("\n"); ++ ++ final ThreadInfo targetThreadInfo = ManagementFactory.getThreadMXBean().getThreadInfo(thread.getId()); ++ ++ messageBuilder.append("Is Suspend: ").append(targetThreadInfo.isSuspended()).append("\n"); ++ messageBuilder.append("Thread State: ").append(targetThreadInfo.getThreadState()).append("\n"); ++ messageBuilder.append("Thread Priority: ").append(targetThreadInfo.getPriority()).append("\n"); ++ messageBuilder.append("Thread Stack Trace:").append("\n"); ++ ++ for (StackTraceElement stackTraceElement : StacktraceDeobfuscator.INSTANCE.deobfuscateStacktrace(thread.getStackTrace())){ ++ messageBuilder.append("\t\t").append(stackTraceElement).append("\n"); ++ } ++ ++ messageBuilder.append("\n"); ++ messageBuilder.append("===================================="); ++ ++ logger.error(messageBuilder.toString()); ++ } ++ ++ public static void globalRegionHeartBeat(){ ++ if (!WatchdogConfig.enabled){ ++ return; ++ } ++ ++ synchronized (keepaliveDataLock){ ++ globalRegionLastKeepalive = Pair.of(Thread.currentThread(),System.nanoTime()); ++ } ++ } ++ ++ public static void tickRegionHeartBeat(){ ++ if (!WatchdogConfig.enabled){ ++ return; ++ } ++ ++ final ThreadedRegionizer.ThreadedRegion currentRegion = TickRegionScheduler.getCurrentRegion(); ++ ++ if (currentRegion == null) { ++ return; ++ } ++ ++ synchronized (keepaliveDataLock){ ++ if (!otherTickRegionKeepalive.containsKey(Thread.currentThread())){ ++ otherTickRegionKeepalive.put(Thread.currentThread(),Pair.of(currentRegion,System.nanoTime())); ++ return; ++ } ++ ++ otherTickRegionKeepalive.replace(Thread.currentThread(),Pair.of(currentRegion,System.nanoTime())); ++ } ++ } ++ ++ public static void onRegionDeath(ThreadedRegionizer.ThreadedRegion currentRegion){ ++ if (!WatchdogConfig.enabled){ ++ return; ++ } ++ ++ synchronized (keepaliveDataLock){ ++ otherTickRegionKeepalive.remove(Thread.currentThread()); ++ } ++ } ++} +\ No newline at end of file +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index dd4fbe5a51e05560343d2ee919d4bc50963e3d70..4d3ba2b02d19cc43a19bc633b9c5df66b85533f7 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -1222,6 +1222,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop packCallbacks = new java.util.concurrent.ConcurrentHashMap<>(); // Paper - adventure resource pack callbacks -@@ -105,6 +106,16 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -103,6 +104,16 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack @Override public void handleKeepAlive(ServerboundKeepAlivePacket packet) { @@ -59,7 +59,7 @@ index 43c8e48ecdf82a17b81fc91c6f602c953067d11c..38564ab781665aeb215734a367bc8727 //PacketUtils.ensureRunningOnSameThread(packet, this, this.player.serverLevel()); // CraftBukkit // Paper - handle ServerboundKeepAlivePacket async if (this.keepAlivePending && packet.getId() == this.keepAliveChallenge) { int i = (int) (Util.getMillis() - this.keepAliveTime); -@@ -225,6 +236,21 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -221,6 +232,21 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack long currentTime = Util.getMillis(); long elapsedTime = currentTime - this.keepAliveTime; diff --git a/patches/server/0053-Leaves-Protocol-Core.patch b/patches/server/0054-Leaves-Protocol-Core.patch similarity index 98% rename from patches/server/0053-Leaves-Protocol-Core.patch rename to patches/server/0054-Leaves-Protocol-Core.patch index cd12769..5d93b2e 100644 --- a/patches/server/0053-Leaves-Protocol-Core.patch +++ b/patches/server/0054-Leaves-Protocol-Core.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Leaves Protocol Core diff --git a/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java b/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java -index fc3d332aa1c1d469cedfe2aaa7102dcd78e25642..bebaa4e7abcbd01dc57fddf2a473b846e887cc7f 100644 +index 1ae61bc6603dd3ac290e3ead20416f9c5b63ff02..168ed2c21aed6a10f3aca259880b1b8bdbf98b78 100644 --- a/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java +++ b/src/main/java/io/papermc/paper/threadedregions/RegionizedServer.java -@@ -313,6 +313,8 @@ public final class RegionizedServer { +@@ -314,6 +314,8 @@ public final class RegionizedServer { // player list MinecraftServer.getServer().getPlayerList().tick(); @@ -36,10 +36,10 @@ index af86f752c33a2990405fea058b7c41c437ba9d46..bada9fae1e7178162429e1f5a1608b9c } diff --git a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java -index 38564ab781665aeb215734a367bc87271efd3d2a..f8ebb4349004e67d399e44588e159528d31c7be0 100644 +index c68910b2a2eb703406fb406a86783cf6ab48651e..f935214ed80fe54038a96a5cd668a072cdf406ec 100644 --- a/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerCommonPacketListenerImpl.java -@@ -141,6 +141,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -139,6 +139,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack @Override public void handleCustomPayload(ServerboundCustomPayloadPacket packet) { @@ -47,7 +47,7 @@ index 38564ab781665aeb215734a367bc87271efd3d2a..f8ebb4349004e67d399e44588e159528 // Paper start - Brand support if (packet.payload() instanceof net.minecraft.network.protocol.common.custom.BrandPayload brandPayload) { this.player.clientBrandName = brandPayload.brand(); -@@ -160,6 +161,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack +@@ -156,6 +157,7 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack String channels = payload.toString(com.google.common.base.Charsets.UTF_8); for (String channel : channels.split("\0")) { this.getCraftPlayer().addChannel(channel); diff --git a/patches/server/0054-Leaves-Bladeren-Protocol.patch b/patches/server/0055-Leaves-Bladeren-Protocol.patch similarity index 100% rename from patches/server/0054-Leaves-Bladeren-Protocol.patch rename to patches/server/0055-Leaves-Bladeren-Protocol.patch diff --git a/patches/server/0055-Leaves-Fix-Bladeren-Protocol.patch b/patches/server/0056-Leaves-Fix-Bladeren-Protocol.patch similarity index 100% rename from patches/server/0055-Leaves-Fix-Bladeren-Protocol.patch rename to patches/server/0056-Leaves-Fix-Bladeren-Protocol.patch diff --git a/patches/server/0056-Leaves-carpet-protocol-support.patch b/patches/server/0057-Leaves-carpet-protocol-support.patch similarity index 100% rename from patches/server/0056-Leaves-carpet-protocol-support.patch rename to patches/server/0057-Leaves-carpet-protocol-support.patch diff --git a/patches/server/0057-Threaded-region-start-tick-and-finished-tick-event.patch b/patches/server/0058-Threaded-region-start-tick-and-finished-tick-event.patch similarity index 100% rename from patches/server/0057-Threaded-region-start-tick-and-finished-tick-event.patch rename to patches/server/0058-Threaded-region-start-tick-and-finished-tick-event.patch