diff options
author | Nassim Jahnke <[email protected]> | 2024-12-17 13:32:46 +0100 |
---|---|---|
committer | Nassim Jahnke <[email protected]> | 2024-12-17 13:32:46 +0100 |
commit | 2d83f05a6c5d6323d9b7962654ec21a644343086 (patch) | |
tree | 8fc3d33667711150d197c116889aad33975c10c6 | |
parent | 7daedfcbc3e40875375a6b2b16e37134390c332e (diff) | |
download | Paper-2d83f05a6c5d6323d9b7962654ec21a644343086.tar.gz Paper-2d83f05a6c5d6323d9b7962654ec21a644343086.zip |
Update watchdog patches
12 files changed, 253 insertions, 426 deletions
diff --git a/feature-patches/1061-Improved-Watchdog-Support.patch b/feature-patches/1061-Improved-Watchdog-Support.patch index 3ed20e43df..90799d6e60 100644 --- a/feature-patches/1061-Improved-Watchdog-Support.patch +++ b/feature-patches/1061-Improved-Watchdog-Support.patch @@ -40,25 +40,28 @@ This is to ensure that if main isn't truely stuck, it's not manipulating state w This also moves all plugins who register "delayed init" tasks to occur just before "Done" so they are properly accounted for and wont trip watchdog on init. -diff --git a/src/main/java/io/papermc/paper/util/LogManagerShutdownThread.java b/src/main/java/io/papermc/paper/util/LogManagerShutdownThread.java +diff --git a/io/papermc/paper/util/LogManagerShutdownThread.java b/io/papermc/paper/util/LogManagerShutdownThread.java new file mode 100644 -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +index 0000000000000000000000000000000000000000..3d7df554b89cff23f64da7ad48b5e4d26ac2baf7 --- /dev/null -+++ b/src/main/java/io/papermc/paper/util/LogManagerShutdownThread.java -@@ -0,0 +0,0 @@ ++++ b/io/papermc/paper/util/LogManagerShutdownThread.java +@@ -0,0 +1,29 @@ +package io.papermc.paper.util; + -+public class LogManagerShutdownThread extends Thread { ++import org.apache.logging.log4j.LogManager; ++ ++public final class LogManagerShutdownThread extends Thread { + + static LogManagerShutdownThread INSTANCE = new LogManagerShutdownThread(); -+ public static final void hook() { ++ ++ public static void hook() { + if (INSTANCE == null) { + throw new IllegalStateException("Cannot re-hook after being unhooked"); + } + Runtime.getRuntime().addShutdownHook(INSTANCE); + } + -+ public static final void unhook() { ++ public static void unhook() { + Runtime.getRuntime().removeShutdownHook(INSTANCE); + INSTANCE = null; + } @@ -69,38 +72,38 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + @Override + public void run() { -+ org.apache.logging.log4j.LogManager.shutdown(); ++ LogManager.shutdown(); + } +} -diff --git a/src/main/java/net/minecraft/CrashReport.java b/src/main/java/net/minecraft/CrashReport.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/CrashReport.java -+++ b/src/main/java/net/minecraft/CrashReport.java -@@ -0,0 +0,0 @@ public class CrashReport { +diff --git a/net/minecraft/CrashReport.java b/net/minecraft/CrashReport.java +index 3e0e88afcf010d9a3d46e48bca5cbdf98fe97544..8bd7999c17c8772451f873966f8c90969aee1482 100644 +--- a/net/minecraft/CrashReport.java ++++ b/net/minecraft/CrashReport.java +@@ -205,6 +205,7 @@ public class CrashReport { } - public static CrashReport forThrowable(Throwable cause, String title) { + public static CrashReport forThrowable(Throwable cause, String description) { + if (cause instanceof ThreadDeath) com.destroystokyo.paper.util.SneakyThrow.sneaky(cause); // Paper while (cause instanceof CompletionException && cause.getCause() != null) { cause = cause.getCause(); } -diff --git a/src/main/java/net/minecraft/server/Main.java b/src/main/java/net/minecraft/server/Main.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/Main.java -+++ b/src/main/java/net/minecraft/server/Main.java -@@ -0,0 +0,0 @@ public class Main { - @SuppressForbidden(reason = "System.out needed before bootstrap") // CraftBukkit - decompile error +diff --git a/net/minecraft/server/Main.java b/net/minecraft/server/Main.java +index 4437283a5d157eede121b98be0112c1067eded5e..fc9ec242743f755a1f0c9ec6bccd11c82375d655 100644 +--- a/net/minecraft/server/Main.java ++++ b/net/minecraft/server/Main.java +@@ -68,6 +68,7 @@ public class Main { + ) @DontObfuscate - public static void main(final OptionSet optionset) { // CraftBukkit - replaces main(String[] astring) + public static void main(final OptionSet optionSet) { // CraftBukkit - replaces main(String[] args) + io.papermc.paper.util.LogManagerShutdownThread.hook(); // Paper SharedConstants.tryDetectVersion(); /* CraftBukkit start - Replace everything - OptionParser optionparser = new OptionParser(); -diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/MinecraftServer.java -+++ b/src/main/java/net/minecraft/server/MinecraftServer.java -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa + OptionParser optionParser = new OptionParser(); +diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java +index 8aa9ae2925ad44d57a27be3e520fcf20e30237d6..30b2bce976e3bf4c8e0b165cac527a685c02aeb1 100644 +--- a/net/minecraft/server/MinecraftServer.java ++++ b/net/minecraft/server/MinecraftServer.java +@@ -287,7 +287,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa public java.util.Queue<Runnable> processQueue = new java.util.concurrent.ConcurrentLinkedQueue<Runnable>(); public int autosavePeriod; // Paper - don't store the vanilla dispatcher @@ -109,17 +112,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // CraftBukkit end // Spigot start public static final int TPS = 20; -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa +@@ -300,6 +300,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa public boolean isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked private final Set<String> pluginsBlockingSleep = new java.util.HashSet<>(); // Paper - API to allow/disallow tick sleeping - + public static final long SERVER_INIT = System.nanoTime(); // Paper - Lag compensation + public volatile Thread shutdownThread; // Paper -+ public volatile boolean abnormalExit = false; // Paper -+ - public static <S extends MinecraftServer> S spin(Function<Thread, S> serverFactory) { ++ public volatile boolean abnormalExit; // Paper + + public static <S extends MinecraftServer> S spin(Function<Thread, S> threadFunction) { ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system - AtomicReference<S> atomicreference = new AtomicReference(); -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa +@@ -393,6 +395,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa } */ // Paper end @@ -127,7 +129,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Runtime.getRuntime().addShutdownHook(new org.bukkit.craftbukkit.util.ServerShutdownThread(this)); // CraftBukkit end this.paperConfigurations = services.paperConfigurations(); // Paper - add paper configuration files -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa +@@ -877,6 +880,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa // CraftBukkit start private boolean hasStopped = false; private boolean hasLoggedStop = false; // Paper - Debugging @@ -135,7 +137,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 private final Object stopLock = new Object(); public final boolean hasStopped() { synchronized (this.stopLock) { -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa +@@ -892,6 +896,10 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa this.hasStopped = true; } if (!hasLoggedStop && isDebugging()) io.papermc.paper.util.TraceUtil.dumpTraceForThread("Server stopped"); // Paper - Debugging @@ -146,10 +148,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 // CraftBukkit end if (this.metricsRecorder.isRecording()) { this.cancelRecordingMetrics(); -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa - ca.spottedleaf.moonrise.common.util.MoonriseCommon.haltExecutors(); +@@ -964,6 +972,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa + this.getProfileCache().save(false); // Paper - Perf: Async GameProfileCache saving } - // Paper end - rewrite chunk system + // Spigot end + // Paper start - Improved watchdog support - move final shutdown items here + Util.shutdownExecutors(); + try { @@ -162,7 +164,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } public String getLocalIp() { -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa +@@ -1056,6 +1073,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa protected void runServer() { try { @@ -170,7 +172,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (!this.initServer()) { throw new IllegalStateException("Failed to initialize server"); } -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa +@@ -1066,6 +1084,17 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa this.server.spark.enableBeforePlugins(); // Paper - spark // Spigot start @@ -188,20 +190,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 org.spigotmc.WatchdogThread.hasStarted = true; // Paper Arrays.fill( this.recentTps, 20 ); // Paper start - further improve server tick loop -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa +@@ -1155,6 +1184,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa JvmProfiler.INSTANCE.onServerTick(this.smoothedTickTimeMillis); } - } catch (Throwable throwable2) { + } catch (Throwable var69) { + // Paper start -+ if (throwable2 instanceof ThreadDeath) { -+ MinecraftServer.LOGGER.error("Main thread terminated by WatchDog due to hard crash", throwable2); ++ if (var69 instanceof ThreadDeath) { ++ MinecraftServer.LOGGER.error("Main thread terminated by WatchDog due to hard crash", var69); + return; + } + // Paper end - MinecraftServer.LOGGER.error("Encountered an unexpected exception", throwable2); - CrashReport crashreport = MinecraftServer.constructOrExtractCrashReport(throwable2); - -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa + LOGGER.error("Encountered an unexpected exception", var69); + CrashReport crashReport = constructOrExtractCrashReport(var69); + this.fillSystemReport(crashReport.getSystemReport()); +@@ -1177,15 +1212,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa this.services.profileCache().clearExecutor(); } @@ -219,9 +221,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + //io.papermc.paper.log.CustomLogManager.forceReset(); // Paper - Reset loggers after shutdown + //this.onServerExit(); // Paper - moved into stop } - } -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa + } +@@ -1289,6 +1324,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa @Override public TickTask wrapRunnable(Runnable runnable) { @@ -234,37 +236,37 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 return new TickTask(this.tickCount, runnable); } -@@ -0,0 +0,0 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa - this.resources.managers.updateStaticRegistryTags(); - this.resources.managers.getRecipeManager().finalizeRecipeLoading(this.worldData.enabledFeatures()); - this.potionBrewing = this.potionBrewing.reload(this.worldData.enabledFeatures()); // Paper - Custom Potion Mixes -- this.getPlayerList().saveAll(); -+ // Paper start -+ if (Thread.currentThread() != this.serverThread) { -+ return; -+ } -+ // this.getPlayerList().saveAll(); // Paper - we don't need to save everything, just advancements // TODO Move this to a different patch -+ for (ServerPlayer player : this.getPlayerList().getPlayers()) { -+ player.getAdvancements().save(); -+ } -+ // Paper end - this.getPlayerList().reloadResources(); - this.functionManager.replaceLibrary(this.resources.managers.getFunctionLibrary()); - this.structureTemplateManager.onResourceManagerReload(this.resources.resourceManager); -diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java -@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface - long j = Util.getNanos() - i; - String s = String.format(Locale.ROOT, "%.3fs", (double) j / 1.0E9D); - -- DedicatedServer.LOGGER.info("Done ({})! For help, type \"help\"", s); -+ DedicatedServer.LOGGER.info("Done preparing level \"{}\" ({})", this.getLevelIdName(), s); // Paper - clarify startup log messages & add total time - if (dedicatedserverproperties.announcePlayerAchievements != null) { - ((GameRules.BooleanValue) this.getGameRules().getRule(GameRules.RULE_ANNOUNCE_ADVANCEMENTS)).set(dedicatedserverproperties.announcePlayerAchievements, this.overworld()); // CraftBukkit - per-world +@@ -2085,7 +2126,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa + this.resources.managers.updateStaticRegistryTags(); + this.resources.managers.getRecipeManager().finalizeRecipeLoading(this.worldData.enabledFeatures()); + this.potionBrewing = this.potionBrewing.reload(this.worldData.enabledFeatures()); // Paper - Custom Potion Mixes +- this.getPlayerList().saveAll(); ++ // Paper start ++ if (Thread.currentThread() != this.serverThread) { ++ return; ++ } ++ // this.getPlayerList().saveAll(); // Paper - we don't need to save everything, just advancements // TODO Move this to a different patch ++ for (ServerPlayer player : this.getPlayerList().getPlayers()) { ++ player.getAdvancements().save(); ++ } ++ // Paper end + this.getPlayerList().reloadResources(); + this.functionManager.replaceLibrary(this.resources.managers.getFunctionLibrary()); + this.structureTemplateManager.onResourceManagerReload(this.resources.resourceManager); +diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java +index 1ad96b964cdcf10b9f81d32d07e03c1a0ab6fe0a..d51d0c56e0cb68556ad366d52312bdb81ed17e9e 100644 +--- a/net/minecraft/server/dedicated/DedicatedServer.java ++++ b/net/minecraft/server/dedicated/DedicatedServer.java +@@ -322,7 +322,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface + this.loadLevel(this.storageSource.getLevelId()); // CraftBukkit + long l = Util.getNanos() - nanos; + String string = String.format(Locale.ROOT, "%.3fs", l / 1.0E9); +- LOGGER.info("Done ({})! For help, type \"help\"", string); ++ LOGGER.info("Done preparing level \"{}\" ({})", this.getLevelIdName(), string); // Paper - clarify startup log messages & add total time + if (properties.announcePlayerAchievements != null) { + this.getGameRules().getRule(GameRules.RULE_ANNOUNCE_ADVANCEMENTS).set(properties.announcePlayerAchievements, this.overworld()); // CraftBukkit - per-world } -@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -418,7 +418,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface // this.remoteStatusListener.stop(); // Paper - don't wait for remote connections } @@ -274,7 +276,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 } @Override -@@ -0,0 +0,0 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface +@@ -726,7 +727,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface @Override public void stopServer() { super.stopServer(); @@ -283,173 +285,52 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 SkullBlockEntity.clear(); } -diff --git a/src/main/java/net/minecraft/server/players/PlayerList.java b/src/main/java/net/minecraft/server/players/PlayerList.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/players/PlayerList.java -+++ b/src/main/java/net/minecraft/server/players/PlayerList.java -@@ -0,0 +0,0 @@ public abstract class PlayerList { +diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java +index d227714de0fe13544779fae6cf0e9ff6af5469c7..393bd2ec0962d3870f5b4cb74200e5467b50cdb8 100644 +--- a/net/minecraft/server/players/PlayerList.java ++++ b/net/minecraft/server/players/PlayerList.java +@@ -513,7 +513,7 @@ public abstract class PlayerList { this.cserver.getPluginManager().callEvent(playerQuitEvent); - entityplayer.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); + player.getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); -- entityplayer.doTick(); // SPIGOT-924 -+ if (server.isSameThread()) entityplayer.doTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) +- player.doTick(); // SPIGOT-924 ++ if (this.server.isSameThread()) player.doTick(); // SPIGOT-924 // Paper - don't tick during emergency shutdowns (Watchdog) // CraftBukkit end // Paper start - Configurable player collision; Remove from collideRule team if needed -diff --git a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -+++ b/src/main/java/net/minecraft/util/thread/BlockableEventLoop.java -@@ -0,0 +0,0 @@ public abstract class BlockableEventLoop<R extends Runnable> implements Profiler - public static boolean isNonRecoverable(Throwable exception) { - return exception instanceof ReportedException reportedException +diff --git a/net/minecraft/util/thread/BlockableEventLoop.java b/net/minecraft/util/thread/BlockableEventLoop.java +index 186c1b2e3599770385150eb7acdcd890aa5835eb..bfea9a2ae5e0bd5dae2873f715d192dfcbe97ee5 100644 +--- a/net/minecraft/util/thread/BlockableEventLoop.java ++++ b/net/minecraft/util/thread/BlockableEventLoop.java +@@ -169,6 +169,6 @@ public abstract class BlockableEventLoop<R extends Runnable> implements Profiler + public static boolean isNonRecoverable(Throwable error) { + return error instanceof ReportedException reportedException ? isNonRecoverable(reportedException.getCause()) -- : exception instanceof OutOfMemoryError || exception instanceof StackOverflowError; -+ : exception instanceof OutOfMemoryError || exception instanceof StackOverflowError || exception instanceof ThreadDeath; // Paper +- : error instanceof OutOfMemoryError || error instanceof StackOverflowError; ++ : error instanceof OutOfMemoryError || error instanceof StackOverflowError || error instanceof ThreadDeath; // Paper } } -diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/Level.java -+++ b/src/main/java/net/minecraft/world/level/Level.java -@@ -0,0 +0,0 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl +diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java +index cb6ca60af3d3f90501e4693a78466b9f7462362d..127e25dab3a5e4df9cdf8eefd0485ea07b7696d9 100644 +--- a/net/minecraft/world/level/Level.java ++++ b/net/minecraft/world/level/Level.java +@@ -863,6 +863,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { try { - tickConsumer.accept(entity); - } catch (Throwable throwable) { -+ if (throwable instanceof ThreadDeath) throw throwable; // Paper + consumerEntity.accept(entity); + } catch (Throwable var6) { ++ if (var6 instanceof ThreadDeath) throw var6; // Paper // Paper start - Prevent block entity and entity crashes final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level().getWorld().getName(), entity.getX(), entity.getY(), entity.getZ()); - MinecraftServer.LOGGER.error(msg, throwable); -diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java -@@ -0,0 +0,0 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p + MinecraftServer.LOGGER.error(msg, var6); +diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java +index d1d0dc13eecb0e0eb3a7839b570a5fe7f62f3fba..205f5a687eb685284a2e403f3eb6bdc694fc5423 100644 +--- a/net/minecraft/world/level/chunk/LevelChunk.java ++++ b/net/minecraft/world/level/chunk/LevelChunk.java +@@ -855,6 +855,7 @@ public class LevelChunk extends ChunkAccess { - gameprofilerfiller.pop(); - } catch (Throwable throwable) { -+ if (throwable instanceof ThreadDeath) throw throwable; // Paper + profilerFiller.pop(); + } catch (Throwable var5) { ++ if (var5 instanceof ThreadDeath) throw var5; // Paper // Paper start - Prevent block entity and entity crashes final String msg = String.format("BlockEntity threw exception at %s:%s,%s,%s", LevelChunk.this.getLevel().getWorld().getName(), this.getPos().getX(), this.getPos().getY(), this.getPos().getZ()); - net.minecraft.server.MinecraftServer.LOGGER.error(msg, throwable); -diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java -@@ -0,0 +0,0 @@ public class ServerShutdownThread extends Thread { - @Override - public void run() { - try { -+ // Paper start - try to shutdown on main -+ server.safeShutdown(false, false); -+ for (int i = 1000; i > 0 && !server.hasStopped(); i -= 100) { -+ Thread.sleep(100); -+ } -+ if (server.hasStopped()) { -+ while (!server.hasFullyShutdown) Thread.sleep(1000); -+ return; -+ } -+ // Looks stalled, close async - org.spigotmc.AsyncCatcher.enabled = false; // Spigot -+ server.forceTicks = true; - this.server.close(); -+ while (!server.hasFullyShutdown) Thread.sleep(1000); -+ } catch (InterruptedException e) { -+ e.printStackTrace(); -+ // Paper end - } finally { -+ org.apache.logging.log4j.LogManager.shutdown(); // Paper - 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/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/RestartCommand.java -+++ b/src/main/java/org/spigotmc/RestartCommand.java -@@ -0,0 +0,0 @@ public class RestartCommand extends Command - // Paper end - - // Paper start - copied from above and modified to return if the hook registered -- private static boolean addShutdownHook(String restartScript) -+ public static boolean addShutdownHook(String restartScript) // Paper - { - String[] split = restartScript.split( " " ); - if ( split.length > 0 && new File( split[0] ).isFile() ) -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -0,0 +0,0 @@ import org.bukkit.Bukkit; - public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThread // Paper - rewrite chunk system - { - -+ public static final boolean DISABLE_WATCHDOG = Boolean.getBoolean("disable.watchdog"); // Paper - Improved watchdog support - private static WatchdogThread instance; - private long timeoutTime; - private boolean restart; -@@ -0,0 +0,0 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre - { - if ( WatchdogThread.instance == null ) - { -+ if (timeoutTime <= 0) timeoutTime = 300; // Paper - WatchdogThread.instance = new WatchdogThread( timeoutTime * 1000L, restart ); - WatchdogThread.instance.start(); - } else -@@ -0,0 +0,0 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre - // Paper start - Logger log = Bukkit.getServer().getLogger(); - long currentTime = WatchdogThread.monotonicMillis(); -- if ( this.lastTick != 0 && this.timeoutTime > 0 && currentTime > this.lastTick + this.earlyWarningEvery && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable -+ MinecraftServer server = MinecraftServer.getServer(); -+ if ( this.lastTick != 0 && this.timeoutTime > 0 && WatchdogThread.hasStarted && (!server.isRunning() || (currentTime > this.lastTick + this.earlyWarningEvery && !DISABLE_WATCHDOG) )) // Paper - add property to disable - { -- boolean isLongTimeout = currentTime > lastTick + timeoutTime; -+ 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 && MinecraftServer.getServer().hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... -+ if ( !isLongTimeout && server.hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... - lastEarlyWarning = currentTime; - if (isLongTimeout) { - // Paper end -@@ -0,0 +0,0 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre - - if ( isLongTimeout ) - { -- if ( this.restart && !MinecraftServer.getServer().hasStopped() ) -+ if ( !server.hasStopped() ) - { -- RestartCommand.restart(); -+ AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us -+ server.forceTicks = true; -+ if (restart) { -+ RestartCommand.addShutdownHook( SpigotConfig.restartScript ); -+ } -+ // try one last chance to safe shutdown on main incase it 'comes back' -+ server.abnormalExit = true; -+ server.safeShutdown(false, restart); -+ try { -+ Thread.sleep(1000); -+ } catch (InterruptedException e) { -+ e.printStackTrace(); -+ } -+ if (!server.hasStopped()) { -+ server.close(); -+ } - } - break; - } // Paper end -diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/resources/log4j2.xml -+++ b/src/main/resources/log4j2.xml -@@ -0,0 +0,0 @@ - <?xml version="1.0" encoding="UTF-8"?> --<Configuration status="WARN"> -+<Configuration status="WARN" shutdownHook="disable"> - <Appenders> - <Queue name="ServerGuiConsole"> - <PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg{nolookups}%n" /> + net.minecraft.server.MinecraftServer.LOGGER.error(msg, var5); diff --git a/feature-patches/1062-Detail-more-information-in-watchdog-dumps.patch b/feature-patches/1062-Detail-more-information-in-watchdog-dumps.patch index 9d5a4deee3..20f825b57b 100644 --- a/feature-patches/1062-Detail-more-information-in-watchdog-dumps.patch +++ b/feature-patches/1062-Detail-more-information-in-watchdog-dumps.patch @@ -6,32 +6,55 @@ Subject: [PATCH] Detail more information in watchdog dumps - Dump position, world, velocity, and uuid for currently ticking entities - Dump player name, player uuid, position, and world for packet handling -diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/Connection.java -+++ b/src/main/java/net/minecraft/network/Connection.java -@@ -0,0 +0,0 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> { +diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java +index 8fe485c5bf79804bb4d1f774f95a92b14a576e80..0bcae6256d3b3fb6b2e0c2f23907d4659b236ef3 100644 +--- a/net/minecraft/network/Connection.java ++++ b/net/minecraft/network/Connection.java +@@ -603,7 +603,13 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> { if (!(this.packetListener instanceof net.minecraft.server.network.ServerLoginPacketListenerImpl loginPacketListener) || loginPacketListener.state != net.minecraft.server.network.ServerLoginPacketListenerImpl.State.VERIFYING || Connection.joinAttemptsThisTick++ < MAX_PER_TICK) { + // Paper start - detailed watchdog information + net.minecraft.network.protocol.PacketUtils.packetProcessing.push(this.packetListener); + try { - tickablepacketlistener.tick(); + tickablePacketListener.tick(); + } finally { + net.minecraft.network.protocol.PacketUtils.packetProcessing.pop(); + } // Paper end - detailed watchdog information } // Paper end - Buffer joins to world } -diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java -+++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java -@@ -0,0 +0,0 @@ public class PacketUtils { - - private static final Logger LOGGER = LogUtils.getLogger(); +diff --git a/net/minecraft/network/protocol/PacketUtils.java b/net/minecraft/network/protocol/PacketUtils.java +index e65c62dbe4c1560ae153e4c4344e9194c783a2f4..4535858701b2bb232b9d2feb2af6551526232ddc 100644 +--- a/net/minecraft/network/protocol/PacketUtils.java ++++ b/net/minecraft/network/protocol/PacketUtils.java +@@ -21,6 +21,8 @@ public class PacketUtils { + public static <T extends PacketListener> void ensureRunningOnSameThread(Packet<T> packet, T processor, BlockableEventLoop<?> executor) throws RunningOnDifferentThreadException { + if (!executor.isSameThread()) { + executor.executeIfPossible(() -> { ++ packetProcessing.push(processor); // Paper - detailed watchdog information ++ try { // Paper - detailed watchdog information + if (processor instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl serverCommonPacketListener && serverCommonPacketListener.processedDisconnect) return; // Paper - Don't handle sync packets for kicked players + if (processor.shouldHandleMessage(packet)) { + try { +@@ -35,6 +37,12 @@ public class PacketUtils { + } else { + LOGGER.debug("Ignoring packet due to disconnection: {}", packet); + } ++ // Paper start - detailed watchdog information ++ } finally { ++ totalMainThreadPacketsProcessed.getAndIncrement(); ++ packetProcessing.pop(); ++ } ++ // Paper end - detailed watchdog information + }); + throw RunningOnDifferentThreadException.RUNNING_ON_DIFFERENT_THREAD; + } +@@ -61,4 +69,22 @@ public class PacketUtils { + packetListener.fillCrashReport(crashReport); + } ++ + // Paper start - detailed watchdog information + public static final java.util.concurrent.ConcurrentLinkedDeque<PacketListener> packetProcessing = new java.util.concurrent.ConcurrentLinkedDeque<>(); + static final java.util.concurrent.atomic.AtomicLong totalMainThreadPacketsProcessed = new java.util.concurrent.atomic.AtomicLong(); @@ -41,46 +64,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + public static java.util.List<PacketListener> getCurrentPacketProcessors() { -+ java.util.List<PacketListener> ret = new java.util.ArrayList<>(4); ++ java.util.List<PacketListener> listeners = new java.util.ArrayList<>(4); + for (PacketListener listener : packetProcessing) { -+ ret.add(listener); ++ listeners.add(listener); + } + -+ return ret; ++ return listeners; + } + // Paper end - detailed watchdog information -+ - public PacketUtils() {} - - public static <T extends PacketListener> void ensureRunningOnSameThread(Packet<T> packet, T listener, ServerLevel world) throws RunningOnDifferentThreadException { -@@ -0,0 +0,0 @@ public class PacketUtils { - public static <T extends PacketListener> void ensureRunningOnSameThread(Packet<T> packet, T listener, BlockableEventLoop<?> engine) throws RunningOnDifferentThreadException { - if (!engine.isSameThread()) { - engine.executeIfPossible(() -> { -+ packetProcessing.push(listener); // Paper - detailed watchdog information -+ try { // Paper - detailed watchdog information - if (listener instanceof ServerCommonPacketListenerImpl serverCommonPacketListener && serverCommonPacketListener.processedDisconnect) return; // CraftBukkit - Don't handle sync packets for kicked players - if (listener.shouldHandleMessage(packet)) { - try { -@@ -0,0 +0,0 @@ public class PacketUtils { - } else { - PacketUtils.LOGGER.debug("Ignoring packet due to disconnection: {}", packet); - } -+ // Paper start - detailed watchdog information -+ } finally { -+ totalMainThreadPacketsProcessed.getAndIncrement(); -+ packetProcessing.pop(); -+ } -+ // Paper end - detailed watchdog information - - }); - throw RunningOnDifferentThreadException.RUNNING_ON_DIFFERENT_THREAD; -diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/server/level/ServerLevel.java -+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe - + } +diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java +index 9cc47bda7197ca3f63b0ede9905c9a13931f84ed..05f45b490e823a455b23b23b26a7da3b447059ea 100644 +--- a/net/minecraft/server/level/ServerLevel.java ++++ b/net/minecraft/server/level/ServerLevel.java +@@ -956,7 +956,26 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + } } + // Paper start - log detailed entity tick information @@ -103,13 +101,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + currentlyTickingEntity.lazySet(entity); + } + // Paper end - log detailed entity tick information - // Spigot start - /*if (!org.spigotmc.ActivationRange.checkIfActive(entity)) { // Paper - comment out EAR 2 - entity.tickCount++; -@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + entity.setOldPosAndRot(); + ProfilerFiller profilerFiller = Profiler.get(); + entity.tickCount++; +@@ -972,6 +991,13 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe + for (Entity entity1 : entity.getPassengers()) { this.tickPassenger(entity, entity1, isActive); // Paper - EAR 2 } - + // Paper start - log detailed entity tick information + } finally { + if (currentlyTickingEntity.get() == entity) { @@ -119,12 +117,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end - log detailed entity tick information } - private void tickPassenger(Entity vehicle, Entity passenger, boolean isActive) { // Paper - EAR 2 -diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/entity/Entity.java -+++ b/src/main/java/net/minecraft/world/entity/Entity.java -@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + private void tickPassenger(Entity ridingEntity, Entity passengerEntity, final boolean isActive) { // Paper - EAR 2 +diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java +index 5a67aa9f1fe103e5622ed6fa93bc4bc25ddbb688..1ff09959aa95d9822ccb6724bbb3f441c768511a 100644 +--- a/net/minecraft/world/entity/Entity.java ++++ b/net/minecraft/world/entity/Entity.java +@@ -956,8 +956,43 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return this.onGround; } @@ -168,8 +166,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 if (this.noPhysics) { this.setPos(this.getX() + movement.x, this.getY() + movement.y, this.getZ() + movement.z); } else { -@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess - gameprofilerfiller.pop(); +@@ -1075,6 +1110,13 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + profilerFiller.pop(); } } + // Paper start - detailed watchdog information @@ -181,115 +179,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Paper end - detailed watchdog information } - private void applyMovementEmissionAndPlaySound(Entity.MovementEmission moveEffect, Vec3 movement, BlockPos landingPos, BlockState landingState) { -@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + private void applyMovementEmissionAndPlaySound(Entity.MovementEmission movementEmission, Vec3 movement, BlockPos pos, BlockState state) { +@@ -4348,7 +4390,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } - public void setDeltaMovement(Vec3 velocity) { + public void setDeltaMovement(Vec3 deltaMovement) { + synchronized (this.posLock) { // Paper - this.deltaMovement = velocity; + this.deltaMovement = deltaMovement; + } // Paper } - public void addDeltaMovement(Vec3 velocity) { -@@ -0,0 +0,0 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess + public void addDeltaMovement(Vec3 addend) { +@@ -4445,7 +4489,9 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess } // Paper end - Fix MC-4 if (this.position.x != x || this.position.y != y || this.position.z != z) { + synchronized (this.posLock) { // Paper this.position = new Vec3(x, y, z); + } // Paper - int i = Mth.floor(x); - int j = Mth.floor(y); - int k = Mth.floor(z); -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -0,0 +0,0 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre - private volatile long lastTick; - private volatile boolean stopping; - -+ // Paper start - log detailed tick information -+ private void dumpEntity(net.minecraft.world.entity.Entity entity) { -+ Logger log = Bukkit.getServer().getLogger(); -+ double posX, posY, posZ; -+ net.minecraft.world.phys.Vec3 mot; -+ double moveStartX, moveStartY, moveStartZ; -+ net.minecraft.world.phys.Vec3 moveVec; -+ synchronized (entity.posLock) { -+ posX = entity.getX(); -+ posY = entity.getY(); -+ posZ = entity.getZ(); -+ mot = entity.getDeltaMovement(); -+ moveStartX = entity.getMoveStartX(); -+ moveStartY = entity.getMoveStartY(); -+ moveStartZ = entity.getMoveStartZ(); -+ moveVec = entity.getMoveVector(); -+ } -+ -+ String entityType = net.minecraft.world.entity.EntityType.getKey(entity.getType()).toString(); -+ java.util.UUID entityUUID = entity.getUUID(); -+ net.minecraft.world.level.Level world = entity.level(); -+ -+ log.log(Level.SEVERE, "Ticking entity: " + entityType + ", entity class: " + entity.getClass().getName()); -+ log.log(Level.SEVERE, "Entity status: removed: " + entity.isRemoved() + ", valid: " + entity.valid + ", alive: " + entity.isAlive() + ", is passenger: " + entity.isPassenger()); -+ log.log(Level.SEVERE, "Entity UUID: " + entityUUID); -+ log.log(Level.SEVERE, "Position: world: '" + (world == null ? "unknown world?" : world.getWorld().getName()) + "' at location (" + posX + ", " + posY + ", " + posZ + ")"); -+ log.log(Level.SEVERE, "Velocity: " + (mot == null ? "unknown velocity" : mot.toString()) + " (in blocks per tick)"); -+ log.log(Level.SEVERE, "Entity AABB: " + entity.getBoundingBox()); -+ if (moveVec != null) { -+ log.log(Level.SEVERE, "Move call information: "); -+ log.log(Level.SEVERE, "Start position: (" + moveStartX + ", " + moveStartY + ", " + moveStartZ + ")"); -+ log.log(Level.SEVERE, "Move vector: " + moveVec.toString()); -+ } -+ } -+ -+ private void dumpTickingInfo() { -+ Logger log = Bukkit.getServer().getLogger(); -+ -+ // ticking entities -+ for (net.minecraft.world.entity.Entity entity : net.minecraft.server.level.ServerLevel.getCurrentlyTickingEntities()) { -+ this.dumpEntity(entity); -+ net.minecraft.world.entity.Entity vehicle = entity.getVehicle(); -+ if (vehicle != null) { -+ log.log(Level.SEVERE, "Detailing vehicle for above entity:"); -+ this.dumpEntity(vehicle); -+ } -+ } -+ -+ // packet processors -+ for (net.minecraft.network.PacketListener packetListener : net.minecraft.network.protocol.PacketUtils.getCurrentPacketProcessors()) { -+ if (packetListener instanceof net.minecraft.server.network.ServerGamePacketListenerImpl) { -+ net.minecraft.server.level.ServerPlayer player = ((net.minecraft.server.network.ServerGamePacketListenerImpl)packetListener).player; -+ long totalPackets = net.minecraft.network.protocol.PacketUtils.getTotalProcessedPackets(); -+ if (player == null) { -+ log.log(Level.SEVERE, "Handling packet for player connection or ticking player connection (null player): " + packetListener); -+ log.log(Level.SEVERE, "Total packets processed on the main thread for all players: " + totalPackets); -+ } else { -+ this.dumpEntity(player); -+ net.minecraft.world.entity.Entity vehicle = player.getVehicle(); -+ if (vehicle != null) { -+ log.log(Level.SEVERE, "Detailing vehicle for above entity:"); -+ this.dumpEntity(vehicle); -+ } -+ log.log(Level.SEVERE, "Total packets processed on the main thread for all players: " + totalPackets); -+ } -+ } else { -+ log.log(Level.SEVERE, "Handling packet for connection: " + packetListener); -+ } -+ } -+ } -+ // Paper end - log detailed tick information -+ - private WatchdogThread(long timeoutTime, boolean restart) - { - super( "Paper Watchdog Thread" ); -@@ -0,0 +0,0 @@ public class WatchdogThread extends ca.spottedleaf.moonrise.common.util.TickThre - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper - ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkTaskScheduler.dumpAllChunkLoadInfo(MinecraftServer.getServer(), isLongTimeout); // Paper - rewrite chunk system -+ this.dumpTickingInfo(); // Paper - log detailed tick information - WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // + int floor = Mth.floor(x); + int floor1 = Mth.floor(y); + int floor2 = Mth.floor(z); diff --git a/paper-server/patches/features/0007-Anti-Xray.patch b/paper-server/patches/features/0007-Anti-Xray.patch index b322872f20..8e51f5c6ae 100644 --- a/paper-server/patches/features/0007-Anti-Xray.patch +++ b/paper-server/patches/features/0007-Anti-Xray.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Anti-Xray diff --git a/io/papermc/paper/FeatureHooks.java b/io/papermc/paper/FeatureHooks.java -index aad9d9687dffb872a12ba0ba39d674895b7474e7..764daee7cd619c56314bcea9a4c35702afcb262d 100644 +index 0eba4fce940b90e67f3746480c040178ba9f5525..3bdbd3d566dee767204d898e0bb4f82f0060d9ca 100644 --- a/io/papermc/paper/FeatureHooks.java +++ b/io/papermc/paper/FeatureHooks.java @@ -7,6 +7,7 @@ import it.unimi.dsi.fastutil.longs.LongSets; @@ -16,7 +16,7 @@ index aad9d9687dffb872a12ba0ba39d674895b7474e7..764daee7cd619c56314bcea9a4c35702 import java.util.List; import java.util.Map; import java.util.Set; -@@ -35,20 +36,25 @@ public final class FeatureHooks { +@@ -36,20 +37,25 @@ public final class FeatureHooks { } public static LevelChunkSection createSection(final Registry<Biome> biomeRegistry, final Level level, final ChunkPos chunkPos, final int chunkSection) { @@ -46,13 +46,6 @@ index aad9d9687dffb872a12ba0ba39d674895b7474e7..764daee7cd619c56314bcea9a4c35702 } public static Set<Long> getSentChunkKeys(final ServerPlayer player) { -@@ -74,4 +80,4 @@ public final class FeatureHooks { - public static boolean isSpiderCollidingWithWorldBorder(final Spider spider) { - return true; // ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.isCollidingWithBorder(spider.level().getWorldBorder(), spider.getBoundingBox().inflate(ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON)) - } --} -\ No newline at end of file -+} diff --git a/net/minecraft/network/protocol/game/ClientboundChunksBiomesPacket.java b/net/minecraft/network/protocol/game/ClientboundChunksBiomesPacket.java index d4872b7f4e9591b3b1c67406312905851303f521..cb41460e94161675e2ab43f4b1b5286ee38e2e13 100644 --- a/net/minecraft/network/protocol/game/ClientboundChunksBiomesPacket.java diff --git a/paper-server/patches/features/0020-Rewrite-dataconverter-system.patch b/paper-server/patches/features/0020-Rewrite-dataconverter-system.patch index 844c0f9320..4e1356ce74 100644 --- a/paper-server/patches/features/0020-Rewrite-dataconverter-system.patch +++ b/paper-server/patches/features/0020-Rewrite-dataconverter-system.patch @@ -30621,10 +30621,10 @@ index 1110ca4075a1bbaa46b66686435dab91b275c945..c2218630c3074c8b3f82364e37503b12 return structureTemplate.save(new CompoundTag()); } diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index d450d4af96716caff4b29a84d1d83ec4010854f0..646c2f2b617ed706021c83c9fc4492860dfdd4e9 100644 +index 7b233bd4c5c373fe38585e0f8d3e6367dd357741..fd6fdb6d7e15633bd01d4f930ee3b15c0dd2ca06 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -301,6 +301,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa +@@ -303,6 +303,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa private final Set<String> pluginsBlockingSleep = new java.util.HashSet<>(); // Paper - API to allow/disallow tick sleeping public static <S extends MinecraftServer> S spin(Function<Thread, S> threadFunction) { diff --git a/paper-server/patches/features/0022-Lag-compensation-ticks.patch b/paper-server/patches/features/0022-Lag-compensation-ticks.patch index 1d692f7144..50c0323115 100644 --- a/paper-server/patches/features/0022-Lag-compensation-ticks.patch +++ b/paper-server/patches/features/0022-Lag-compensation-ticks.patch @@ -8,10 +8,10 @@ Areas affected by lag comepnsation: - Eating food items diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 646c2f2b617ed706021c83c9fc4492860dfdd4e9..8aa9ae2925ad44d57a27be3e520fcf20e30237d6 100644 +index fd6fdb6d7e15633bd01d4f930ee3b15c0dd2ca06..22dc6bec58702762e4a31415f9aed2df2b3ad0d6 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -299,6 +299,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa +@@ -301,6 +301,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa public final io.papermc.paper.configuration.PaperConfigurations paperConfigurations; // Paper - add paper configuration files public boolean isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked private final Set<String> pluginsBlockingSleep = new java.util.HashSet<>(); // Paper - API to allow/disallow tick sleeping @@ -19,7 +19,7 @@ index 646c2f2b617ed706021c83c9fc4492860dfdd4e9..8aa9ae2925ad44d57a27be3e520fcf20 public static <S extends MinecraftServer> S spin(Function<Thread, S> threadFunction) { ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system -@@ -1564,6 +1565,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa +@@ -1566,6 +1567,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa for (ServerLevel serverLevel : this.getAllLevels()) { serverLevel.hasPhysicsEvent = org.bukkit.event.block.BlockPhysicsEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - BlockPhysicsEvent serverLevel.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent diff --git a/paper-server/patches/sources/io/papermc/paper/FeatureHooks.java.patch b/paper-server/patches/sources/io/papermc/paper/FeatureHooks.java.patch index 69bf0f769f..5c3b4d6856 100644 --- a/paper-server/patches/sources/io/papermc/paper/FeatureHooks.java.patch +++ b/paper-server/patches/sources/io/papermc/paper/FeatureHooks.java.patch @@ -1,6 +1,6 @@ --- /dev/null +++ b/io/papermc/paper/FeatureHooks.java -@@ -1,0 +_,77 @@ +@@ -1,0 +_,84 @@ +package io.papermc.paper; + +import io.papermc.paper.command.PaperSubcommand; @@ -16,6 +16,7 @@ +import net.minecraft.core.Registry; +import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; +import net.minecraft.server.level.ServerPlayer; ++import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.monster.Spider; +import net.minecraft.world.level.ChunkPos; +import net.minecraft.world.level.Level; @@ -77,4 +78,10 @@ + public static boolean isSpiderCollidingWithWorldBorder(final Spider spider) { + return true; // ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.isCollidingWithBorder(spider.level().getWorldBorder(), spider.getBoundingBox().inflate(ca.spottedleaf.moonrise.patches.collisions.CollisionUtil.COLLISION_EPSILON)) + } ++ ++ public static void dumpTickingInfo() { ++ } ++ ++ private static void dumpEntity(final Entity entity) { ++ } +} diff --git a/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch b/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch index eb9c14d4a5..3aa38008fc 100644 --- a/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch @@ -41,7 +41,7 @@ @Nullable private KeyPair keyPair; @Nullable -@@ -271,10 +_,33 @@ +@@ -271,10 +_,35 @@ private final SuppressedExceptionCollector suppressedExceptions = new SuppressedExceptionCollector(); private final DiscontinuousFrame tickFrame; @@ -54,7 +54,7 @@ + public java.util.Queue<Runnable> processQueue = new java.util.concurrent.ConcurrentLinkedQueue<Runnable>(); + public int autosavePeriod; + // Paper - don't store the vanilla dispatcher -+ private boolean forceTicks; ++ public boolean forceTicks; + // CraftBukkit end + // Spigot start + public static final int TPS = 20; @@ -63,6 +63,8 @@ + @Deprecated(forRemoval = true) // Paper + public final double[] recentTps = new double[ 3 ]; + // Spigot end ++ public volatile boolean hasFullyShutdown; // Paper - Improved watchdog support ++ public volatile boolean abnormalExit; // Paper - Improved watchdog support + public final io.papermc.paper.configuration.PaperConfigurations paperConfigurations; // Paper - add paper configuration files + public boolean isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked + private final Set<String> pluginsBlockingSleep = new java.util.HashSet<>(); // Paper - API to allow/disallow tick sleeping diff --git a/paper-server/patches/sources/net/minecraft/server/dedicated/DedicatedServer.java.patch b/paper-server/patches/sources/net/minecraft/server/dedicated/DedicatedServer.java.patch index def9b71a6f..243d71c069 100644 --- a/paper-server/patches/sources/net/minecraft/server/dedicated/DedicatedServer.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/dedicated/DedicatedServer.java.patch @@ -301,7 +301,7 @@ } @Override -@@ -271,12 +_,14 @@ +@@ -271,12 +_,15 @@ } if (this.rconThread != null) { @@ -314,6 +314,7 @@ + // this.remoteStatusListener.stop(); // Paper - don't wait for remote connections } + ++ this.hasFullyShutdown = true; // Paper - Improved watchdog support + System.exit(0); // CraftBukkit } diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/paper-server/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java index c6e8441e29..e8e93538df 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java @@ -12,11 +12,27 @@ public class ServerShutdownThread extends Thread { @Override public void run() { try { + // Paper start - try to shutdown on main + server.safeShutdown(false, false); + for (int i = 1000; i > 0 && !server.hasStopped(); i -= 100) { + Thread.sleep(100); + } + if (server.hasStopped()) { + while (!server.hasFullyShutdown) Thread.sleep(1000); + return; + } + // Looks stalled, close async org.spigotmc.AsyncCatcher.enabled = false; // Spigot + server.forceTicks = true; this.server.close(); + while (!server.hasFullyShutdown) Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + // Paper end } finally { + org.apache.logging.log4j.LogManager.shutdown(); // Paper try { - net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Use TerminalConsoleAppender + //net.minecrell.terminalconsole.TerminalConsoleAppender.close(); // Paper - Move into stop } catch (Exception e) { } } diff --git a/paper-server/src/main/java/org/spigotmc/RestartCommand.java b/paper-server/src/main/java/org/spigotmc/RestartCommand.java index b87f66ad04..3287d39951 100644 --- a/paper-server/src/main/java/org/spigotmc/RestartCommand.java +++ b/paper-server/src/main/java/org/spigotmc/RestartCommand.java @@ -105,7 +105,7 @@ public class RestartCommand extends Command { // Paper end // Paper start - copied from above and modified to return if the hook registered - private static boolean addShutdownHook(String restartScript) { + public static boolean addShutdownHook(String restartScript) { String[] split = restartScript.split(" "); if (split.length > 0 && new File(split[0]).isFile()) { Thread shutdownHook = new Thread(() -> { diff --git a/paper-server/src/main/java/org/spigotmc/WatchdogThread.java b/paper-server/src/main/java/org/spigotmc/WatchdogThread.java index 7fa7816014..0c67e3297e 100644 --- a/paper-server/src/main/java/org/spigotmc/WatchdogThread.java +++ b/paper-server/src/main/java/org/spigotmc/WatchdogThread.java @@ -1,17 +1,19 @@ package org.spigotmc; +import io.papermc.paper.FeatureHooks; +import io.papermc.paper.configuration.GlobalConfiguration; import java.lang.management.ManagementFactory; import java.lang.management.MonitorInfo; import java.lang.management.ThreadInfo; import java.util.logging.Level; import java.util.logging.Logger; -import io.papermc.paper.configuration.GlobalConfiguration; import net.minecraft.server.MinecraftServer; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.CraftServer; public class WatchdogThread extends Thread { + public static final boolean DISABLE_WATCHDOG = Boolean.getBoolean("disable.watchdog"); // Paper - Improved watchdog support private static WatchdogThread instance; private long timeoutTime; private boolean restart; @@ -36,6 +38,7 @@ public class WatchdogThread extends Thread { public static void doStart(int timeoutTime, boolean restart) { if (WatchdogThread.instance == null) { + if (timeoutTime <= 0) timeoutTime = 300; // Paper WatchdogThread.instance = new WatchdogThread(timeoutTime * 1000L, restart); WatchdogThread.instance.start(); } else { @@ -60,14 +63,15 @@ public class WatchdogThread extends Thread { // Paper start Logger logger = Bukkit.getServer().getLogger(); long currentTime = WatchdogThread.monotonicMillis(); - if (this.lastTick != 0 && this.timeoutTime > 0 && currentTime > this.lastTick + this.earlyWarningEvery && !Boolean.getBoolean("disable.watchdog")) { // Paper - Add property to disable - boolean isLongTimeout = currentTime > this.lastTick + this.timeoutTime; + MinecraftServer server = MinecraftServer.getServer(); + if (this.lastTick != 0 && this.timeoutTime > 0 && WatchdogThread.hasStarted && (!server.isRunning() || (currentTime > this.lastTick + this.earlyWarningEvery && !DISABLE_WATCHDOG))) { // Paper - add property to disable + boolean isLongTimeout = currentTime > this.lastTick + this.timeoutTime || (!server.isRunning() && !server.hasStopped() && currentTime > this.lastTick + 1000); // Don't spam early warning dumps if (!isLongTimeout && (this.earlyWarningEvery <= 0 || !hasStarted || currentTime < this.lastEarlyWarning + this.earlyWarningEvery || currentTime < this.lastTick + this.earlyWarningDelay)) continue; - if (!isLongTimeout && MinecraftServer.getServer().hasStopped()) + if (!isLongTimeout && server.hasStopped()) continue; // Don't spam early watchdog warnings during shutdown, we'll come back to this... this.lastEarlyWarning = currentTime; if (isLongTimeout) { @@ -106,6 +110,7 @@ public class WatchdogThread extends Thread { // Paper end - Different message for short timeout logger.log(Level.SEVERE, "------------------------------"); logger.log(Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):"); // Paper + FeatureHooks.dumpTickingInfo(); // Paper - log detailed tick information WatchdogThread.dumpThread(ManagementFactory.getThreadMXBean().getThreadInfo(MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE), logger); logger.log(Level.SEVERE, "------------------------------"); @@ -123,8 +128,23 @@ public class WatchdogThread extends Thread { logger.log(Level.SEVERE, "------------------------------"); if (isLongTimeout) { - if (this.restart && !MinecraftServer.getServer().hasStopped()) { - RestartCommand.restart(); + if (!server.hasStopped()) { + AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us + server.forceTicks = true; + if (this.restart) { + RestartCommand.addShutdownHook(SpigotConfig.restartScript); + } + // try one last chance to safe shutdown on main incase it 'comes back' + server.abnormalExit = true; + server.safeShutdown(false, this.restart); + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + if (!server.hasStopped()) { + server.close(); + } } break; } diff --git a/paper-server/src/main/resources/log4j2.xml b/paper-server/src/main/resources/log4j2.xml index 637d64da99..d2a75850af 100644 --- a/paper-server/src/main/resources/log4j2.xml +++ b/paper-server/src/main/resources/log4j2.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<Configuration status="WARN"> +<Configuration status="WARN" shutdownHook="disable"> <Appenders> <Queue name="ServerGuiConsole"> <PatternLayout pattern="[%d{HH:mm:ss} %level]: %msg{nolookups}%n" /> |