2019-07-05 04:13:38 +02:00
|
|
|
From f9e21fd4b2937c80e0fc254517495108d4e0425c Mon Sep 17 00:00:00 2001
|
2018-08-12 19:27:23 +02:00
|
|
|
From: miclebrick <miclebrick@outlook.com>
|
|
|
|
Date: Wed, 8 Aug 2018 15:30:52 -0400
|
|
|
|
Subject: [PATCH] Add Early Warning Feature to WatchDog
|
|
|
|
|
|
|
|
Detect when the server has been hung for a long duration, and start printing
|
|
|
|
thread dumps at an interval until the point of crash.
|
|
|
|
|
|
|
|
This will help diagnose what was going on in that time before the crash.
|
|
|
|
|
|
|
|
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
2019-07-05 04:13:38 +02:00
|
|
|
index 207e5d3e23..a13c8c68b6 100644
|
2018-08-12 19:27:23 +02:00
|
|
|
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
|
|
|
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
2018-10-19 02:44:59 +02:00
|
|
|
@@ -25,6 +25,7 @@ import org.bukkit.configuration.file.YamlConfiguration;
|
2018-08-12 19:27:23 +02:00
|
|
|
import co.aikar.timings.Timings;
|
|
|
|
import co.aikar.timings.TimingsManager;
|
2018-10-19 02:44:59 +02:00
|
|
|
import org.spigotmc.SpigotConfig;
|
2018-08-12 19:27:23 +02:00
|
|
|
+import org.spigotmc.WatchdogThread;
|
|
|
|
|
|
|
|
public class PaperConfig {
|
|
|
|
|
2019-05-06 09:20:16 +02:00
|
|
|
@@ -312,6 +313,14 @@ public class PaperConfig {
|
2018-08-12 19:27:23 +02:00
|
|
|
}
|
|
|
|
}
|
2018-08-12 19:27:23 +02:00
|
|
|
|
2018-08-12 19:27:23 +02:00
|
|
|
+ public static int watchdogPrintEarlyWarningEvery = 5000;
|
|
|
|
+ public static int watchdogPrintEarlyWarningDelay = 10000;
|
|
|
|
+ private static void watchdogEarlyWarning() {
|
|
|
|
+ watchdogPrintEarlyWarningEvery = getInt("settings.watchdog.early-warning-every", 5000);
|
|
|
|
+ watchdogPrintEarlyWarningDelay = getInt("settings.watchdog.early-warning-delay", 10000);
|
|
|
|
+ WatchdogThread.doStart(SpigotConfig.timeoutTime, SpigotConfig.restartOnCrash );
|
|
|
|
+ }
|
2018-08-12 19:27:23 +02:00
|
|
|
+
|
2018-08-29 18:26:24 +02:00
|
|
|
public static int tabSpamIncrement = 1;
|
2018-08-12 19:27:23 +02:00
|
|
|
public static int tabSpamLimit = 500;
|
|
|
|
private static void tabSpamLimiters() {
|
2018-08-12 19:27:23 +02:00
|
|
|
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
|
2019-07-05 04:13:38 +02:00
|
|
|
index 946803e2be..fe8647bbc6 100644
|
2018-08-12 19:27:23 +02:00
|
|
|
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
|
|
|
|
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
|
2019-06-25 15:55:44 +02:00
|
|
|
@@ -850,6 +850,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
|
2019-05-05 04:23:25 +02:00
|
|
|
this.a(this.serverPing);
|
2018-08-12 19:27:23 +02:00
|
|
|
|
|
|
|
// Spigot start
|
2018-08-17 00:11:35 +02:00
|
|
|
+ org.spigotmc.WatchdogThread.hasStarted = true; // Paper
|
2018-08-12 19:27:23 +02:00
|
|
|
Arrays.fill( recentTps, 20 );
|
2019-05-22 05:58:00 +02:00
|
|
|
long start = System.nanoTime(), curTime, tickSection = start; // Paper - Further improve server tick loop
|
2018-08-26 20:11:49 +02:00
|
|
|
lastTick = start - TICK_TIME; // Paper
|
2018-12-13 02:41:11 +01:00
|
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
2019-07-05 04:13:38 +02:00
|
|
|
index 26de8263dd..e7ac058fc7 100644
|
2018-12-13 02:41:11 +01:00
|
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
2019-07-05 04:13:38 +02:00
|
|
|
@@ -757,6 +757,7 @@ public final class CraftServer implements Server {
|
2018-12-13 02:41:11 +01:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public void reload() {
|
|
|
|
+ org.spigotmc.WatchdogThread.hasStarted = false; // Paper - Disable watchdog early timeout on reload
|
|
|
|
reloadCount++;
|
|
|
|
configuration = YamlConfiguration.loadConfiguration(getConfigFile());
|
|
|
|
commandsConfiguration = YamlConfiguration.loadConfiguration(getCommandsConfigFile());
|
2019-07-05 04:13:38 +02:00
|
|
|
@@ -857,6 +858,7 @@ public final class CraftServer implements Server {
|
2018-12-13 02:41:11 +01:00
|
|
|
enablePlugins(PluginLoadOrder.STARTUP);
|
|
|
|
enablePlugins(PluginLoadOrder.POSTWORLD);
|
|
|
|
getPluginManager().callEvent(new ServerLoadEvent(ServerLoadEvent.LoadType.RELOAD));
|
|
|
|
+ org.spigotmc.WatchdogThread.hasStarted = true; // Paper - Disable watchdog early timeout on reload
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2018-08-12 19:27:23 +02:00
|
|
|
diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java
|
2019-07-05 04:13:38 +02:00
|
|
|
index 6c5430ff94..4b8581f0ed 100644
|
2018-08-12 19:27:23 +02:00
|
|
|
--- a/src/main/java/org/spigotmc/SpigotConfig.java
|
|
|
|
+++ b/src/main/java/org/spigotmc/SpigotConfig.java
|
2019-01-01 04:15:55 +01:00
|
|
|
@@ -225,7 +225,7 @@ public class SpigotConfig
|
2018-08-12 19:27:23 +02:00
|
|
|
restartScript = getString( "settings.restart-script", restartScript );
|
|
|
|
restartMessage = transform( getString( "messages.restart", "Server is restarting" ) );
|
|
|
|
commands.put( "restart", new RestartCommand( "restart" ) );
|
|
|
|
- WatchdogThread.doStart( timeoutTime, restartOnCrash );
|
|
|
|
+ //WatchdogThread.doStart( timeoutTime, restartOnCrash ); // Paper - moved to PaperConfig
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean bungee;
|
|
|
|
diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java
|
2019-07-05 04:13:38 +02:00
|
|
|
index 9532aada82..a1d93200e6 100644
|
2018-08-12 19:27:23 +02:00
|
|
|
--- a/src/main/java/org/spigotmc/WatchdogThread.java
|
|
|
|
+++ b/src/main/java/org/spigotmc/WatchdogThread.java
|
|
|
|
@@ -5,6 +5,7 @@ import java.lang.management.MonitorInfo;
|
|
|
|
import java.lang.management.ThreadInfo;
|
|
|
|
import java.util.logging.Level;
|
|
|
|
import java.util.logging.Logger;
|
|
|
|
+import com.destroystokyo.paper.PaperConfig;
|
|
|
|
import net.minecraft.server.MinecraftServer;
|
|
|
|
import org.bukkit.Bukkit;
|
|
|
|
|
|
|
|
@@ -13,6 +14,10 @@ public class WatchdogThread extends Thread
|
|
|
|
|
|
|
|
private static WatchdogThread instance;
|
|
|
|
private final long timeoutTime;
|
|
|
|
+ private final long earlyWarningEvery; // Paper - Timeout time for just printing a dump but not restarting
|
|
|
|
+ private final long earlyWarningDelay; // Paper
|
|
|
|
+ public static volatile boolean hasStarted; // Paper
|
|
|
|
+ private long lastEarlyWarning; // Paper - Keep track of short dump times to avoid spamming console with short dumps
|
|
|
|
private final boolean restart;
|
|
|
|
private volatile long lastTick;
|
|
|
|
private volatile boolean stopping;
|
|
|
|
@@ -22,6 +27,8 @@ public class WatchdogThread extends Thread
|
|
|
|
super( "Paper Watchdog Thread" );
|
|
|
|
this.timeoutTime = timeoutTime;
|
|
|
|
this.restart = restart;
|
|
|
|
+ earlyWarningEvery = Math.min(PaperConfig.watchdogPrintEarlyWarningEvery, timeoutTime); // Paper
|
|
|
|
+ earlyWarningDelay = Math.min(PaperConfig.watchdogPrintEarlyWarningDelay, timeoutTime); // Paper
|
|
|
|
}
|
|
|
|
|
2018-11-24 06:28:04 +01:00
|
|
|
private static long monotonicMillis()
|
|
|
|
@@ -56,10 +63,17 @@ public class WatchdogThread extends Thread
|
2018-08-17 00:11:35 +02:00
|
|
|
{
|
2018-08-12 19:27:23 +02:00
|
|
|
while ( !stopping )
|
|
|
|
{
|
2018-08-17 00:11:35 +02:00
|
|
|
- //
|
2018-11-24 06:28:04 +01:00
|
|
|
- if ( lastTick != 0 && monotonicMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable
|
2018-08-17 00:11:35 +02:00
|
|
|
+ // Paper start
|
2018-11-24 06:28:04 +01:00
|
|
|
+ Logger log = Bukkit.getServer().getLogger();
|
|
|
|
+ long currentTime = monotonicMillis();
|
2018-08-17 00:11:35 +02:00
|
|
|
+ if ( lastTick != 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") )
|
2018-08-12 19:27:23 +02:00
|
|
|
{
|
2018-11-24 06:28:04 +01:00
|
|
|
- Logger log = Bukkit.getServer().getLogger();
|
2018-08-12 19:27:23 +02:00
|
|
|
+ boolean isLongTimeout = currentTime > lastTick + timeoutTime;
|
2018-08-12 19:27:23 +02:00
|
|
|
+ // Don't spam early warning dumps
|
2018-08-12 19:27:23 +02:00
|
|
|
+ if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue;
|
|
|
|
+ lastEarlyWarning = currentTime;
|
2018-11-24 06:28:04 +01:00
|
|
|
+ if (isLongTimeout) {
|
2018-08-12 19:27:23 +02:00
|
|
|
+ // Paper end
|
2018-11-24 06:28:04 +01:00
|
|
|
log.log( Level.SEVERE, "------------------------------" );
|
|
|
|
log.log( Level.SEVERE, "The server has stopped responding! This is (probably) not a Paper bug." ); // Paper
|
|
|
|
log.log( Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author" );
|
|
|
|
@@ -89,29 +103,46 @@ public class WatchdogThread extends Thread
|
2018-08-12 19:27:23 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Paper end
|
|
|
|
+ } else
|
|
|
|
+ {
|
2018-10-24 21:05:39 +02:00
|
|
|
+ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---");
|
2018-08-12 19:27:23 +02:00
|
|
|
+ log.log(Level.SEVERE, "The server has not responded for " + (currentTime - lastTick) / 1000 + " seconds! Creating thread dump");
|
2018-08-12 19:27:23 +02:00
|
|
|
+ }
|
|
|
|
+ // Paper end - Different message for short timeout
|
|
|
|
log.log( Level.SEVERE, "------------------------------" );
|
2019-05-05 04:23:25 +02:00
|
|
|
log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper
|
|
|
|
dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log );
|
2018-08-12 19:27:23 +02:00
|
|
|
log.log( Level.SEVERE, "------------------------------" );
|
|
|
|
//
|
|
|
|
+ // Paper start - Only print full dump on long timeouts
|
|
|
|
+ if ( isLongTimeout )
|
|
|
|
+ {
|
|
|
|
log.log( Level.SEVERE, "Entire Thread Dump:" );
|
|
|
|
ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true );
|
|
|
|
for ( ThreadInfo thread : threads )
|
2018-08-12 19:27:23 +02:00
|
|
|
{
|
|
|
|
dumpThread( thread, log );
|
|
|
|
}
|
|
|
|
+ } else {
|
|
|
|
+ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
log.log( Level.SEVERE, "------------------------------" );
|
|
|
|
|
2018-08-17 18:09:08 +02:00
|
|
|
+ if ( isLongTimeout )
|
|
|
|
+ {
|
2018-08-12 19:27:23 +02:00
|
|
|
if ( restart )
|
|
|
|
{
|
2018-08-12 19:27:23 +02:00
|
|
|
RestartCommand.restart();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
+ } // Paper end
|
|
|
|
}
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
- sleep( 10000 );
|
|
|
|
+ sleep( 1000 ); // Paper - Reduce check time to every second instead of every ten seconds, more consistent and allows for short timeout
|
|
|
|
} catch ( InterruptedException ex )
|
|
|
|
{
|
|
|
|
interrupt();
|
|
|
|
--
|
2019-06-25 03:47:58 +02:00
|
|
|
2.22.0
|
2018-08-12 19:27:23 +02:00
|
|
|
|