Add integrated server watchdog
This commit is contained in:
parent
3b56f00b82
commit
10149e9f87
|
|
@ -20,11 +20,15 @@ import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||||
import net.minecraftforge.fml.ModContainer;
|
import net.minecraftforge.fml.ModContainer;
|
||||||
import net.minecraftforge.fml.ModList;
|
import net.minecraftforge.fml.ModList;
|
||||||
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
|
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
|
||||||
|
import net.minecraftforge.fml.event.server.FMLServerStartedEvent;
|
||||||
|
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
|
||||||
import net.minecraftforge.fml.network.NetworkEvent;
|
import net.minecraftforge.fml.network.NetworkEvent;
|
||||||
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
|
import org.embeddedt.modernfix.core.ModernFixMixinPlugin;
|
||||||
|
import org.embeddedt.modernfix.core.config.ModernFixConfig;
|
||||||
import org.embeddedt.modernfix.load.LoadEvents;
|
import org.embeddedt.modernfix.load.LoadEvents;
|
||||||
import org.embeddedt.modernfix.packet.EntityIDSyncPacket;
|
import org.embeddedt.modernfix.packet.EntityIDSyncPacket;
|
||||||
import org.embeddedt.modernfix.screen.DeferredLevelLoadingScreen;
|
import org.embeddedt.modernfix.screen.DeferredLevelLoadingScreen;
|
||||||
|
import org.embeddedt.modernfix.world.IntegratedWatchdog;
|
||||||
|
|
||||||
import java.lang.management.ManagementFactory;
|
import java.lang.management.ManagementFactory;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
|
@ -219,4 +223,13 @@ public class ModernFixClient {
|
||||||
|
|
||||||
context.get().setPacketHandled(true);
|
context.get().setPacketHandled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void onServerStarted(FMLServerStartingEvent event) {
|
||||||
|
if(ModernFixConfig.INTEGRATED_SERVER_WATCHDOG.get()) {
|
||||||
|
IntegratedWatchdog watchdog = new IntegratedWatchdog(event.getServer());
|
||||||
|
watchdog.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ public class ModernFixConfig {
|
||||||
public static ForgeConfigSpec.BooleanValue ENABLE_DEBUG_RELOADER;
|
public static ForgeConfigSpec.BooleanValue ENABLE_DEBUG_RELOADER;
|
||||||
|
|
||||||
public static ForgeConfigSpec.BooleanValue REBUILD_BLOCKSTATES_ASYNC;
|
public static ForgeConfigSpec.BooleanValue REBUILD_BLOCKSTATES_ASYNC;
|
||||||
|
public static ForgeConfigSpec.BooleanValue INTEGRATED_SERVER_WATCHDOG;
|
||||||
|
|
||||||
public static Set<ResourceLocation> jeiPluginBlacklist;
|
public static Set<ResourceLocation> jeiPluginBlacklist;
|
||||||
|
|
||||||
|
|
@ -43,6 +44,9 @@ public class ModernFixConfig {
|
||||||
REBUILD_BLOCKSTATES_ASYNC = COMMON_BUILDER
|
REBUILD_BLOCKSTATES_ASYNC = COMMON_BUILDER
|
||||||
.comment("Rebuild blockstate cache asynchronously. Should work with most mods, but can be disabled.")
|
.comment("Rebuild blockstate cache asynchronously. Should work with most mods, but can be disabled.")
|
||||||
.define("rebuild_blockstate_cache_async", true);
|
.define("rebuild_blockstate_cache_async", true);
|
||||||
|
INTEGRATED_SERVER_WATCHDOG = COMMON_BUILDER
|
||||||
|
.comment("Automatically output a thread dump if the integrated server spends too long on one tick")
|
||||||
|
.define("integrated_server_watchdog", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
package org.embeddedt.modernfix.world;
|
||||||
|
|
||||||
|
import net.minecraft.DefaultUncaughtExceptionHandlerWithName;
|
||||||
|
import net.minecraft.Util;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import java.lang.management.ManagementFactory;
|
||||||
|
import java.lang.management.ThreadInfo;
|
||||||
|
import java.lang.management.ThreadMXBean;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public class IntegratedWatchdog extends Thread {
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger();
|
||||||
|
|
||||||
|
private final MinecraftServer server;
|
||||||
|
|
||||||
|
private static final long MAX_TICK_DELTA = 40*1000;
|
||||||
|
|
||||||
|
public IntegratedWatchdog(MinecraftServer server) {
|
||||||
|
this.server = server;
|
||||||
|
this.setDaemon(true);
|
||||||
|
this.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandlerWithName(LOGGER));
|
||||||
|
this.setName("ModernFix integrated server watchdog");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
while(server.isRunning()) {
|
||||||
|
long nextTick = this.server.getNextTickTime();
|
||||||
|
long curTime = Util.getMillis();
|
||||||
|
if((curTime - nextTick) > MAX_TICK_DELTA) {
|
||||||
|
LOGGER.error("A single server tick has taken {}, more than {} milliseconds", (nextTick - curTime), MAX_TICK_DELTA);
|
||||||
|
ThreadMXBean threadmxbean = ManagementFactory.getThreadMXBean();
|
||||||
|
ThreadInfo[] athreadinfo = threadmxbean.dumpAllThreads(true, true);
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Thread Dump:\n");
|
||||||
|
for(ThreadInfo threadinfo : athreadinfo) {
|
||||||
|
sb.append(threadinfo);
|
||||||
|
StackTraceElement[] elements = threadinfo.getStackTrace();
|
||||||
|
if(elements.length > 8) {
|
||||||
|
sb.append("extended trace:\n");
|
||||||
|
for(int i = 8; i < elements.length; i++) {
|
||||||
|
sb.append("\tat ");
|
||||||
|
sb.append(elements[i]);
|
||||||
|
sb.append('\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append('\n');
|
||||||
|
}
|
||||||
|
LOGGER.error(sb);
|
||||||
|
nextTick = 0;
|
||||||
|
curTime = 0;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Thread.sleep(nextTick + MAX_TICK_DELTA - curTime);
|
||||||
|
} catch(InterruptedException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user