From 8b9d2faa117b9a5d1ccde714981fd4b339b8a418 Mon Sep 17 00:00:00 2001 From: CraftBukkit/Spigot Date: Mon, 21 Apr 2014 12:43:08 +0100 Subject: [PATCH] Prevent NoClassDefError crash and notify on crash By: David --- .../minecraft/world/level/Level.java.patch | 41 +++++++++++-------- .../level/redstone/NeighborUpdater.java.patch | 7 +++- .../java/org/spigotmc/WatchdogThread.java | 7 ++++ 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/world/level/Level.java.patch b/paper-server/patches/sources/net/minecraft/world/level/Level.java.patch index afca8fe969..d788f05025 100644 --- a/paper-server/patches/sources/net/minecraft/world/level/Level.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/Level.java.patch @@ -57,7 +57,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable { public static final Codec> RESOURCE_KEY_CODEC = ResourceKey.codec(Registries.DIMENSION); -@@ -121,23 +144,62 @@ +@@ -121,23 +144,63 @@ private final DamageSources damageSources; private long subTickCount; @@ -83,6 +83,7 @@ + public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot + + public final SpigotTimings.WorldTimingsHandler timings; // Spigot ++ public static BlockPos lastPhysicsProblem; // Spigot + + public CraftWorld getWorld() { + return this.world; @@ -129,7 +130,7 @@ } }; } else { -@@ -145,11 +207,48 @@ +@@ -145,11 +208,48 @@ } this.thread = Thread.currentThread(); @@ -183,7 +184,7 @@ } @Override -@@ -207,6 +306,18 @@ +@@ -207,6 +307,18 @@ @Override public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) { @@ -202,12 +203,12 @@ if (this.isOutsideBuildHeight(pos)) { return false; } else if (!this.isClientSide && this.isDebug()) { -@@ -214,44 +325,117 @@ +@@ -214,44 +326,123 @@ } else { LevelChunk chunk = this.getChunkAt(pos); Block block = state.getBlock(); - BlockState iblockdata1 = chunk.setBlockState(pos, state, (flags & 64) != 0); -+ + + // CraftBukkit start - capture blockstates + boolean captured = false; + if (this.captureBlockStates && !this.capturedBlockStates.containsKey(pos)) { @@ -216,7 +217,7 @@ + captured = true; + } + // CraftBukkit end - ++ + BlockState iblockdata1 = chunk.setBlockState(pos, state, (flags & 64) != 0, (flags & 1024) == 0); // CraftBukkit custom NO_PLACE flag + if (iblockdata1 == null) { @@ -275,7 +276,13 @@ + // CraftBukkit start + if (!this.captureBlockStates) { // Don't notify clients or update physics while capturing blockstates + // Modularize client and physic updates -+ this.notifyAndUpdatePhysics(pos, chunk, iblockdata1, state, iblockdata2, flags, maxUpdateDepth); ++ // Spigot start ++ try { ++ this.notifyAndUpdatePhysics(pos, chunk, iblockdata1, state, iblockdata2, flags, maxUpdateDepth); ++ } catch (StackOverflowError ex) { ++ Level.lastPhysicsProblem = new BlockPos(pos); ++ } ++ // Spigot end + } + // CraftBukkit end + @@ -335,7 +342,7 @@ public void onBlockStateChange(BlockPos pos, BlockState oldBlock, BlockState newBlock) {} -@@ -340,6 +524,14 @@ +@@ -340,6 +531,14 @@ @Override public BlockState getBlockState(BlockPos pos) { @@ -350,7 +357,7 @@ if (this.isOutsideBuildHeight(pos)) { return Blocks.VOID_AIR.defaultBlockState(); } else { -@@ -440,12 +632,15 @@ +@@ -440,12 +639,15 @@ ProfilerFiller gameprofilerfiller = Profiler.get(); gameprofilerfiller.push("blockEntities"); @@ -366,7 +373,7 @@ Iterator iterator = this.blockEntityTickers.iterator(); boolean flag = this.tickRateManager().runsNormally(); -@@ -459,13 +654,16 @@ +@@ -459,13 +661,16 @@ } } @@ -383,15 +390,15 @@ } catch (Throwable throwable) { CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity"); CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked"); -@@ -510,13 +708,29 @@ +@@ -510,13 +715,29 @@ @Nullable @Override public BlockEntity getBlockEntity(BlockPos pos) { - return this.isOutsideBuildHeight(pos) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(pos).getBlockEntity(pos, LevelChunk.EntityCreationType.IMMEDIATE)); + // CraftBukkit start + return this.getBlockEntity(pos, true); -+ } -+ + } + + @Nullable + public BlockEntity getBlockEntity(BlockPos blockposition, boolean validate) { + if (this.capturedTileEntities.containsKey(blockposition)) { @@ -399,8 +406,8 @@ + } + // CraftBukkit end + return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EntityCreationType.IMMEDIATE)); - } - ++ } ++ public void setBlockEntity(BlockEntity blockEntity) { BlockPos blockposition = blockEntity.getBlockPos(); @@ -414,7 +421,7 @@ this.getChunkAt(blockposition).addAndRegisterBlockEntity(blockEntity); } } -@@ -643,7 +857,7 @@ +@@ -643,7 +864,7 @@ for (int k = 0; k < j; ++k) { EnderDragonPart entitycomplexpart = aentitycomplexpart[k]; @@ -423,7 +430,7 @@ if (t0 != null && predicate.test(t0)) { result.add(t0); -@@ -912,7 +1126,7 @@ +@@ -912,7 +1133,7 @@ public static enum ExplosionInteraction implements StringRepresentable { diff --git a/paper-server/patches/sources/net/minecraft/world/level/redstone/NeighborUpdater.java.patch b/paper-server/patches/sources/net/minecraft/world/level/redstone/NeighborUpdater.java.patch index 86c3e41aec..d54de0c799 100644 --- a/paper-server/patches/sources/net/minecraft/world/level/redstone/NeighborUpdater.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/redstone/NeighborUpdater.java.patch @@ -18,7 +18,7 @@ public interface NeighborUpdater { -@@ -50,6 +56,17 @@ +@@ -50,7 +56,22 @@ static void executeUpdate(Level world, BlockState state, BlockPos pos, Block sourceBlock, @Nullable Orientation orientation, boolean notify) { try { @@ -34,5 +34,10 @@ + } + // CraftBukkit end state.handleNeighborChanged(world, pos, sourceBlock, orientation, notify); ++ // Spigot Start ++ } catch (StackOverflowError ex) { ++ world.lastPhysicsProblem = new BlockPos(pos); ++ // Spigot End } catch (Throwable throwable) { CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception while updating neighbours"); + CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being updated"); diff --git a/paper-server/src/main/java/org/spigotmc/WatchdogThread.java b/paper-server/src/main/java/org/spigotmc/WatchdogThread.java index 065ed3823f..c4bf7053d8 100644 --- a/paper-server/src/main/java/org/spigotmc/WatchdogThread.java +++ b/paper-server/src/main/java/org/spigotmc/WatchdogThread.java @@ -74,6 +74,13 @@ public class WatchdogThread extends Thread 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!):" ); WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log );