Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove halt on server shutdown, Add config option instead #290

Merged
merged 3 commits into from
Jun 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions patches/minecraft/net/minecraft/server/MinecraftServer.java.patch
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -244,11 +_,30 @@
@@ -244,11 +_,41 @@
private final StructureTemplateManager structureTemplateManager;
protected final WorldData worldData;
private volatile boolean isSaving;
Expand Down Expand Up @@ -28,7 +28,18 @@
- 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_ENABLE.getValue()) {
+ int sleep_ms = org.kettingpowered.ketting.config.KettingConfig.getInstance().HALT_THREADDUMP_SLEEP.getValue();
+ if (sleep_ms > 0)
+ try{
+ Thread.sleep(sleep_ms);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ org.spigotmc.WatchdogThread.doEntireThreadDump();
+ }
+ if (org.kettingpowered.ketting.config.KettingConfig.getInstance().HALT_HALT.getValue()) Runtime.getRuntime().halt(0);
+ if (org.kettingpowered.ketting.config.KettingConfig.getInstance().HALT_EXIT.getValue()) System.exit(0);
}, "Server thread");
thread.setUncaughtExceptionHandler((p_177909_, p_177910_) -> {
LOGGER.error("Uncaught exception in server thread", p_177910_);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.jetbrains.annotations.NotNull;
import org.kettingpowered.ketting.config.value.Value;
import org.kettingpowered.ketting.config.value.types.BooleanValue;
import org.kettingpowered.ketting.config.value.types.IntValue;
import org.kettingpowered.ketting.core.Ketting;

import java.lang.reflect.Field;
Expand Down Expand Up @@ -42,5 +43,9 @@ 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_EXIT = new BooleanValue("ketting.halt.exit", false, "If true, Ketting will call System.exit(255), once it is supposed to regularly shutdown. This is useful, if some plugins or mods keep the server up unintentionally.");
public final BooleanValue HALT_HALT = new BooleanValue("ketting.halt.halt", true, "If true, Ketting will call Runtime.getRuntime().halt(), once it is supposed to regularly shutdown. Overrides 'ketting.halt.exit'. THIS SKIPS SHUTDOWN HOOKS. SOME STUFF MIGHT BREAK! IF YOU CAN, ENABLE 'ketting.halt.exit' INSTEAD!");
public final IntValue HALT_THREADDUMP_SLEEP = new IntValue("ketting.halt.thread_dump.sleep_time", 5000, "If true, Ketting will sleep this many seconds before printing the thread-dump.");
public final BooleanValue HALT_THREADDUMP_ENABLE = new BooleanValue("ketting.halt.thread_dump.enabled", 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
}
46 changes: 26 additions & 20 deletions src/main/java/org/spigotmc/WatchdogThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -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() )
{
Expand All @@ -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)
{
Expand All @@ -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 )
{
Expand Down
Loading