diff --git a/src/main/java/net/minecraft/server/CrashReport.java b/src/main/java/net/minecraft/server/CrashReport.java | |
index 3de19c998..c7dc8787c 100644 | |
--- a/src/main/java/net/minecraft/server/CrashReport.java | |
+++ b/src/main/java/net/minecraft/server/CrashReport.java | |
@@ -257,6 +257,7 @@ public class CrashReport { | |
} | |
public static CrashReport a(Throwable throwable, String s) { | |
+ if (throwable instanceof ThreadDeath) com.destroystokyo.paper.util.SneakyThrow.sneaky(throwable); // Paper | |
while (throwable instanceof CompletionException && throwable.getCause() != null) { | |
throwable = throwable.getCause(); | |
} | |
diff --git a/src/main/java/net/minecraft/server/DedicatedServer.java b/src/main/java/net/minecraft/server/DedicatedServer.java | |
index 1ef7890da..e62ca0543 100644 | |
--- a/src/main/java/net/minecraft/server/DedicatedServer.java | |
+++ b/src/main/java/net/minecraft/server/DedicatedServer.java | |
@@ -750,7 +750,7 @@ public class DedicatedServer extends MinecraftServer implements IMinecraftServer | |
@Override | |
public void stop() { | |
super.stop(); | |
- SystemUtils.f(); | |
+ //SystemUtils.f(); // Paper - moved into super | |
} | |
@Override | |
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java | |
index 36fff92f3..a386c1ab4 100644 | |
--- a/src/main/java/net/minecraft/server/MinecraftServer.java | |
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java | |
@@ -144,6 +144,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas | |
private final ResourcePackRepository<ResourcePackLoader> resourcePackRepository; | |
@Nullable | |
private ResourcePackSourceFolder resourcePackFolder; | |
+ public volatile Thread shutdownThread; // Paper | |
public CommandDispatcher commandDispatcher; | |
private final CraftingManager craftingManager; | |
private final TagRegistry tagRegistry; | |
@@ -737,7 +738,12 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas | |
// CraftBukkit start - prevent double stopping on multiple threads | |
synchronized(stopLock) { | |
if (hasStopped) return; | |
+ shutdownThread = Thread.currentThread(); | |
hasStopped = true; | |
+ org.spigotmc.WatchdogThread.doStop(); // Paper | |
+ if (!isMainThread()) { | |
+ this.getThread().stop(); | |
+ } | |
} | |
// CraftBukkit end | |
MinecraftServer.LOGGER.info("Stopping server"); | |
@@ -794,8 +800,18 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas | |
this.getUserCache().c(false); // Paper | |
} | |
// Spigot end | |
+ // Paper start - move final shutdown items here | |
+ LOGGER.info("Flushing Chunk IO"); | |
com.destroystokyo.paper.io.PaperFileIOThread.Holder.INSTANCE.close(true, true); // Paper | |
- System.exit(0); // Paper | |
+ LOGGER.info("Closing Thread Pool"); | |
+ SystemUtils.shutdownServerThreadPool(); // Paper | |
+ LOGGER.info("Closing Server"); | |
+ try { | |
+ net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender | |
+ } catch (Exception e) { | |
+ } | |
+ this.exit(); | |
+ // Paper end | |
} | |
public String getServerIp() { | |
@@ -887,6 +903,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas | |
// Spigot End | |
public void run() { | |
+ boolean isThreadDeath = false; // Paper | |
try { | |
if (this.init()) { | |
this.nextTick = SystemUtils.getMonotonicMillis(); | |
@@ -951,6 +968,13 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas | |
this.a((CrashReport) null); | |
} | |
} catch (Throwable throwable) { | |
+ // Paper start | |
+ if (throwable instanceof ThreadDeath) { | |
+ MinecraftServer.LOGGER.error("Main thread terminated by WatchDog due to hard crash", throwable); | |
+ isThreadDeath = true; | |
+ return; | |
+ } | |
+ // Paper end | |
MinecraftServer.LOGGER.error("Encountered an unexpected exception", throwable); | |
// Spigot Start | |
if ( throwable.getCause() != null ) | |
@@ -982,14 +1006,14 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas | |
} catch (Throwable throwable1) { | |
MinecraftServer.LOGGER.error("Exception stopping the server", throwable1); | |
} finally { | |
- org.spigotmc.WatchdogThread.doStop(); // Spigot | |
+ //org.spigotmc.WatchdogThread.doStop(); // Spigot // Paper - move into stop | |
// CraftBukkit start - Restore terminal to original settings | |
try { | |
- net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender | |
+ //net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Move into stop | |
} catch (Exception ignored) { | |
} | |
// CraftBukkit end | |
- this.exit(); | |
+ //this.exit(); // Paper - moved into stop | |
} | |
} | |
@@ -1040,6 +1064,12 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas | |
@Override | |
protected TickTask postToMainThread(Runnable runnable) { | |
+ // Paper start - anything that does try to post to main during watchdog crash, run on watchdog | |
+ if (this.hasStopped && Thread.currentThread().equals(shutdownThread)) { | |
+ runnable.run(); | |
+ runnable = () -> {}; | |
+ } | |
+ // Paper end | |
return new TickTask(this.ticks, runnable); | |
} | |
diff --git a/src/main/java/net/minecraft/server/PlayerList.java b/src/main/java/net/minecraft/server/PlayerList.java | |
index 6d6fbf2f5..0e1703c9d 100644 | |
--- a/src/main/java/net/minecraft/server/PlayerList.java | |
+++ b/src/main/java/net/minecraft/server/PlayerList.java | |
@@ -411,7 +411,7 @@ public abstract class PlayerList { | |
cserver.getPluginManager().callEvent(playerQuitEvent); | |
entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); | |
- entityplayer.playerTick();// SPIGOT-924 | |
+ if (server.isMainThread()) entityplayer.playerTick();// SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) | |
// CraftBukkit end | |
// Paper start - Remove from collideRule team if needed | |
diff --git a/src/main/java/net/minecraft/server/SystemUtils.java b/src/main/java/net/minecraft/server/SystemUtils.java | |
index dc6d03062..bc8b90466 100644 | |
--- a/src/main/java/net/minecraft/server/SystemUtils.java | |
+++ b/src/main/java/net/minecraft/server/SystemUtils.java | |
@@ -109,6 +109,7 @@ public class SystemUtils { | |
return SystemUtils.c; | |
} | |
+ public static void shutdownServerThreadPool() { f(); } // Paper - OBFHELPER | |
public static void f() { | |
SystemUtils.c.shutdown(); | |
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java | |
index 5fa045998..09b03afff 100644 | |
--- a/src/main/java/net/minecraft/server/World.java | |
+++ b/src/main/java/net/minecraft/server/World.java | |
@@ -786,6 +786,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { | |
gameprofilerfiller.exit(); | |
} catch (Throwable throwable) { | |
+ if (throwable instanceof ThreadDeath) throw throwable; // Paper | |
// Paper start - Prevent tile entity and entity crashes | |
String msg = "TileEntity threw exception at " + tileentity.world.getWorld().getName() + ":" + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ(); | |
System.err.println(msg); | |
@@ -861,6 +862,7 @@ public abstract class World implements GeneratorAccess, AutoCloseable { | |
try { | |
consumer.accept(entity); | |
} catch (Throwable throwable) { | |
+ if (throwable instanceof ThreadDeath) throw throwable; // Paper | |
// Paper start - Prevent tile entity and entity crashes | |
String msg = "Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ(); | |
System.err.println(msg); | |
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java | |
index 8cc0f66ce..dcc44be61 100644 | |
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java | |
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java | |
@@ -1705,7 +1705,7 @@ public final class CraftServer implements Server { | |
@Override | |
public boolean isPrimaryThread() { | |
- return Thread.currentThread().equals(console.serverThread); // Paper - Fix issues with detecting main thread properly | |
+ return Thread.currentThread().equals(console.serverThread) || Thread.currentThread().equals(net.minecraft.server.MinecraftServer.getServer().shutdownThread); // Paper - Fix issues with detecting main thread properly, the only time Watchdog will be used is during a crash shutdown which is a "try our best" scenario | |
} | |
@Override | |
diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java | |
index f255c448a..899a52520 100644 | |
--- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java | |
+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java | |
@@ -30,7 +30,7 @@ public class ServerShutdownThread extends Thread { | |
// Paper end | |
} finally { | |
try { | |
- net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender | |
+ //net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Move into stop | |
} catch (Exception e) { | |
} | |
} | |
diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java | |
index 6dda6d168..acc880c7c 100644 | |
--- a/src/main/java/org/spigotmc/WatchdogThread.java | |
+++ b/src/main/java/org/spigotmc/WatchdogThread.java | |
@@ -67,10 +67,10 @@ public class WatchdogThread extends Thread | |
// Paper start | |
Logger log = Bukkit.getServer().getLogger(); | |
long currentTime = monotonicMillis(); | |
- if ( lastTick != 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) | |
+ MinecraftServer server = MinecraftServer.getServer(); | |
+ if ( !server.isRunning() || (lastTick != 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog")) ) | |
{ | |
- MinecraftServer server = MinecraftServer.getServer(); | |
- boolean isLongTimeout = currentTime > lastTick + timeoutTime || !server.isRunning(); | |
+ boolean isLongTimeout = currentTime > lastTick + timeoutTime || (!server.isRunning() && !server.hasStopped() && currentTime > lastTick + 1000); | |
// Don't spam early warning dumps | |
if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue; | |
if ( !isLongTimeout && server.hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment