diff --git a/patches/minecraft/net/minecraft/server/MinecraftServer.java.patch b/patches/minecraft/net/minecraft/server/MinecraftServer.java.patch index a147695171..8a39da093f 100644 --- a/patches/minecraft/net/minecraft/server/MinecraftServer.java.patch +++ b/patches/minecraft/net/minecraft/server/MinecraftServer.java.patch @@ -1,6 +1,6 @@ --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -244,11 +_,30 @@ +@@ -244,11 +_,31 @@ private final StructureTemplateManager structureTemplateManager; protected final WorldData worldData; private volatile boolean isSaving; @@ -28,7 +28,8 @@ - Thread thread = new Thread(() -> { + Thread thread = new Thread(net.minecraftforge.fml.util.thread.SidedThreadGroups.SERVER, () -> { atomicreference.get().runServer(); -+ Runtime.getRuntime().halt(0); //Ketting - fix server hanging on exit ++ if (org.kettingpowered.ketting.config.KettingConfig.getInstance().HALT_THREADDUMP.getValue()) org.spigotmc.WatchdogThread.doEntireThreadDump(); ++ if (org.kettingpowered.ketting.config.KettingConfig.getInstance().HALT_FORCE.getValue()) Runtime.getRuntime().halt(0); }, "Server thread"); thread.setUncaughtExceptionHandler((p_177909_, p_177910_) -> { LOGGER.error("Uncaught exception in server thread", p_177910_); diff --git a/src/main/java/org/kettingpowered/ketting/config/KettingConfig.java b/src/main/java/org/kettingpowered/ketting/config/KettingConfig.java index 125ed4681d..56dda86dd9 100644 --- a/src/main/java/org/kettingpowered/ketting/config/KettingConfig.java +++ b/src/main/java/org/kettingpowered/ketting/config/KettingConfig.java @@ -42,5 +42,7 @@ public KettingConfig(@NotNull String fileName) { public final BooleanValue OVERWRITE_FORGE_PERMISSIONS = new BooleanValue("forge.overwrite_forge_permissions", false, "--- WARNING - THIS WILL COMPLETELY DISABLE FORGE PERMISSION CHECKS --- Overwrite Forge permissions with Bukkit permissions, makes it possible to use a permission manager plugin for modded commands. If true, Forge permissions will be set to 'forge.command.MODDEDCOMMAND' where MODDEDCOMMAND is the name of the modded command."); public final BooleanValue MERGE_WORLD_SYSTEMS = new BooleanValue("ketting.merge_world_systems", false, "If true, this will attempt to merge both the Forge and Bukkit world system into one, making dimensions exist in the world folder, and Bukkit worlds in their own folder."); + public final BooleanValue HALT_FORCE = new BooleanValue("ketting.halt.force", false, "If true, Ketting will forcibly halt the server, once it is supposed to regularly shutdown. This is useful, if some plugins or mods keep the server up unintentionally."); + public final BooleanValue HALT_THREADDUMP = new BooleanValue("ketting.halt.thread_dump", false, "If true, Ketting will print a Stacktrace of all threads once the server is supposed to regularly shutdown. This option is intended to aid debugging for the option 'ketting.force.halt'."); //End of config values } diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java index 0d3e4543f5..3396c54e59 100644 --- a/src/main/java/org/spigotmc/WatchdogThread.java +++ b/src/main/java/org/spigotmc/WatchdogThread.java @@ -74,26 +74,7 @@ public void run() log.log( Level.SEVERE, "If you are unsure or still think this is a Spigot bug, please report to https://www.spigotmc.org/" ); log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" ); log.log( Level.SEVERE, "Spigot version: " + Bukkit.getServer().getVersion() ); - // - if ( net.minecraft.world.level.Level.lastPhysicsProblem != null ) - { - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "During the run of the server, a physics stackoverflow was supressed" ); - log.log( Level.SEVERE, "near " + net.minecraft.world.level.Level.lastPhysicsProblem ); - } - // - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Spigot!):" ); - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // - log.log( Level.SEVERE, "Entire Thread Dump:" ); - ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true ); - for ( ThreadInfo thread : threads ) - { - dumpThread( thread, log ); - } - log.log( Level.SEVERE, "------------------------------" ); + doEntireThreadDump(); if ( restart && !MinecraftServer.getServer().hasStopped() ) { @@ -111,6 +92,30 @@ public void run() } } } + + public static void doEntireThreadDump(){ + Logger log = Bukkit.getServer().getLogger(); + // + if ( net.minecraft.world.level.Level.lastPhysicsProblem != null ) + { + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "During the run of the server, a physics stackoverflow was supressed" ); + log.log( Level.SEVERE, "near " + net.minecraft.world.level.Level.lastPhysicsProblem ); + } + // + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Spigot!):" ); + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); + log.log( Level.SEVERE, "------------------------------" ); + // + log.log( Level.SEVERE, "Entire Thread Dump:" ); + ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true ); + for ( ThreadInfo thread : threads ) + { + dumpThread( thread, log ); + } + log.log( Level.SEVERE, "------------------------------" ); + } private static void dumpThread(ThreadInfo thread, Logger log) { @@ -120,6 +125,7 @@ private static void dumpThread(ThreadInfo thread, Logger log) log.log( Level.SEVERE, "\tPID: " + thread.getThreadId() + " | Suspended: " + thread.isSuspended() + " | Native: " + thread.isInNative() + + " | Daemon: " + thread.isDaemon() + " | State: " + thread.getThreadState() ); if ( thread.getLockedMonitors().length != 0 ) {