mirror of
https://github.com/Dreeam-qwq/Gale.git
synced 2025-12-22 00:09:25 +00:00
114 lines
6.3 KiB
Diff
114 lines
6.3 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Martijn Muijsers <martijnmuijsers@live.nl>
|
|
Date: Fri, 3 Feb 2023 23:52:49 +0100
|
|
Subject: [PATCH] Watch for blocking base threads
|
|
|
|
License: AGPL-3.0 (https://www.gnu.org/licenses/agpl-3.0.html)
|
|
Gale - https://galemc.org
|
|
|
|
diff --git a/build.gradle.kts b/build.gradle.kts
|
|
index 00508c2b7a0aa9ecdd0c8709a559f26de17a0004..e01986477360b1dbe991af6667e726e8ac656246 100644
|
|
--- a/build.gradle.kts
|
|
+++ b/build.gradle.kts
|
|
@@ -15,6 +15,7 @@ dependencies {
|
|
exclude("io.papermc.paper", "paper-api")
|
|
}
|
|
// Gale end - project setup
|
|
+ implementation("io.projectreactor.tools:blockhound:1.0.7.RELEASE") // Gale - base thread pool - watch for blocking base threads
|
|
// Paper start
|
|
implementation("org.jline:jline-terminal-jansi:3.21.0")
|
|
implementation("net.minecrell:terminalconsoleappender:1.3.0")
|
|
@@ -169,11 +170,13 @@ fun TaskContainer.registerRunTask(
|
|
if (providers.gradleProperty("paper.runDisableWatchdog").getOrElse("false") == "true") {
|
|
systemProperty("disable.watchdog", true)
|
|
}
|
|
+ systemProperty("gale.detect.thread.blocks", true) // Gale - base thread pool - watch for blocking base threads
|
|
|
|
val memoryGb = providers.gradleProperty("paper.runMemoryGb").getOrElse("2")
|
|
val modifiedJvmArgs = jvmArgs ?: arrayListOf()
|
|
modifiedJvmArgs.addAll(listOf("-Xms${memoryGb}G", "-Xmx${memoryGb}G"))
|
|
modifiedJvmArgs.add("--add-modules=jdk.incubator.vector") // Gale - Pufferfish - SIMD support
|
|
+ modifiedJvmArgs.add("-XX:+AllowRedefinitionToAddDeleteMethods") // Gale - base thread pool - watch for blocking base threads
|
|
jvmArgs = modifiedJvmArgs
|
|
|
|
doFirst {
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/Main.java b/src/main/java/org/bukkit/craftbukkit/Main.java
|
|
index fab5d1c1531fa89113bef6d17df8437b0aec4582..95d8715928a0ddccdabcb76090a3b5bdd143c5a5 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/Main.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/Main.java
|
|
@@ -4,18 +4,20 @@ import java.io.File;
|
|
import java.io.IOException;
|
|
import java.text.DateFormat;
|
|
import java.text.SimpleDateFormat;
|
|
-import java.util.Arrays;
|
|
-import java.util.Calendar;
|
|
-import java.util.Date;
|
|
-import java.util.List;
|
|
+import java.util.*;
|
|
import java.util.concurrent.TimeUnit;
|
|
+import java.util.function.Consumer;
|
|
import java.util.logging.Level;
|
|
import java.util.logging.Logger;
|
|
import joptsimple.OptionParser;
|
|
import joptsimple.OptionSet;
|
|
+import net.minecraft.server.MinecraftServer;
|
|
import net.minecraft.util.ExceptionCollector;
|
|
import net.minecraft.world.level.lighting.LayerLightEventListener;
|
|
import net.minecrell.terminalconsole.TerminalConsoleAppender; // Paper
|
|
+import org.galemc.gale.executor.thread.BaseThread;
|
|
+import org.spigotmc.WatchdogThread;
|
|
+import reactor.blockhound.BlockHound;
|
|
|
|
public class Main {
|
|
public static boolean useJline = true;
|
|
@@ -48,6 +50,49 @@ public class Main {
|
|
// Gale end - include time in startup logs
|
|
|
|
public static void main(String[] args) {
|
|
+ // Gale start - base thread pool - watch for blocking base threads
|
|
+ if (Boolean.getBoolean("gale.detect.thread.blocks")) {
|
|
+ printlnStartupInfoToSystemOut("Initializing blocking base thread detection...");
|
|
+ try {
|
|
+ var builder = BlockHound.builder();
|
|
+ // Mark base threads as intended to be non-blocking (except the WatchdogThread, which obviously sleeps until needed)
|
|
+ builder.nonBlockingThreadPredicate(currentPredicate -> currentPredicate.or(thread -> thread instanceof BaseThread && !(thread instanceof WatchdogThread)));
|
|
+ // Set the callback when a base thread blocks
|
|
+ builder.blockingMethodCallback(blockingMethod -> {
|
|
+ if (MinecraftServer.SERVER == null) {
|
|
+ // Allow blocking before the server has finished initializing
|
|
+ return;
|
|
+ }
|
|
+ String message = "A base thread (" + Thread.currentThread() + ") started blocking:";
|
|
+ if (MinecraftServer.LOGGER != null) {
|
|
+ MinecraftServer.LOGGER.error(message);
|
|
+ } else {
|
|
+ printlnStartupErrorToSystemOut(message);
|
|
+ }
|
|
+ new Error(blockingMethod.toString()).printStackTrace();
|
|
+ });
|
|
+ // Allow busy waiting
|
|
+ var blockingMethodsField = builder.getClass().getDeclaredField("blockingMethods");
|
|
+ blockingMethodsField.setAccessible(true);
|
|
+ Map<String, Map<String, Set<String>>> blockingMethods = (Map<String, Map<String, Set<String>>>) blockingMethodsField.get(builder);
|
|
+ Map<String, Set<String>> threadBlockingMethods = blockingMethods.get("java/lang/Thread");
|
|
+ threadBlockingMethods.remove("onSpinWait");
|
|
+ threadBlockingMethods.remove("yield");
|
|
+ // Allow base threads to block in the intended way
|
|
+ builder.allowBlockingCallsInside("org.galemc.gale.executor.thread.BaseThread", "waitUntilSignalled");
|
|
+ // Allow the ServerThread to block during initialization
|
|
+ builder.allowBlockingCallsInside("net.minecraft.server.dedicated.DedicatedServer", "initServer");
|
|
+ // Install BlockHound
|
|
+ builder.install();
|
|
+ printlnStartupInfoToSystemOut("Blocking base thread detection is enabled.");
|
|
+ } catch (Exception e) {
|
|
+ // BlockHound instrumentation failed, which probably means the needed JVM flag is missing
|
|
+ printlnStartupInfoToSystemOut("Blocking base thread detection is disabled.");
|
|
+ printlnStartupInfoToSystemOut("When it is enabled, unexpected thread blocks can be automatically resolved to improve performance.");
|
|
+ printlnStartupInfoToSystemOut("To enable it, add \"-XX:+AllowRedefinitionToAddDeleteMethods\" to your startup flags, BEFORE the \"-jar\".");
|
|
+ }
|
|
+ }
|
|
+ // Gale end - base thread pool - watch for blocking base threads
|
|
// Paper start
|
|
final String warnWhenLegacyFormattingDetected = String.join(".", "net", "kyori", "adventure", "text", "warnWhenLegacyFormattingDetected");
|
|
if (false && System.getProperty(warnWhenLegacyFormattingDetected) == null) {
|