Paper/patches/server/0053-Add-exception-reporting-event.patch
Jason bc127ea819
Updated Upstream (Bukkit/CraftBukkit/Spigot) (#6222)
Upstream has released updates that appear to apply and compile correctly.
This update has not been tested by PaperMC and as with ANY update, please do your own testing

Bukkit Changes:
eec4aab0 SPIGOT-6657: Add getPlayer to SheepDyeWoolEvent
205213c6 SPIGOT-6656: CauldronLevelChangeEvent is not fired correctly when dripstone fills the cauldron

CraftBukkit Changes:
b8c522d5 SPIGOT-6657: Add getPlayer to SheepDyeWoolEvent
f04a77dc SPIGOT-6656: CauldronLevelChangeEvent is not fired correctly when dripstone fills the cauldron
d1dbcebc SPIGOT-6653: Canceling snow bucket placement removes snow from bucket
4f34a67b #891: Fix scheduler task ID overflow and duplication issues

Spigot Changes:
d03d7f12 BUILDTOOLS-604: Rebuild patches
2021-07-18 09:41:53 +02:00

257 lines
15 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Joseph Hirschfeld <joe@ibj.io>
Date: Thu, 3 Mar 2016 03:15:41 -0600
Subject: [PATCH] Add exception reporting event
diff --git a/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..f699ce18ca044f813e194ef2786b7ea853ea86e7
--- /dev/null
+++ b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java
@@ -0,0 +1,38 @@
+package com.destroystokyo.paper;
+
+import com.google.common.base.Preconditions;
+import org.bukkit.craftbukkit.scheduler.CraftTask;
+import com.destroystokyo.paper.event.server.ServerExceptionEvent;
+import com.destroystokyo.paper.exception.ServerSchedulerException;
+
+/**
+ * Reporting wrapper to catch exceptions not natively
+ */
+public class ServerSchedulerReportingWrapper implements Runnable {
+
+ private final CraftTask internalTask;
+
+ public ServerSchedulerReportingWrapper(CraftTask internalTask) {
+ this.internalTask = Preconditions.checkNotNull(internalTask, "internalTask");
+ }
+
+ @Override
+ public void run() {
+ try {
+ internalTask.run();
+ } catch (RuntimeException e) {
+ internalTask.getOwner().getServer().getPluginManager().callEvent(
+ new ServerExceptionEvent(new ServerSchedulerException(e, internalTask))
+ );
+ throw e;
+ } catch (Throwable t) {
+ internalTask.getOwner().getServer().getPluginManager().callEvent(
+ new ServerExceptionEvent(new ServerSchedulerException(t, internalTask))
+ ); //Do not rethrow, since it is not permitted with Runnable#run
+ }
+ }
+
+ public CraftTask getInternalTask() {
+ return internalTask;
+ }
+}
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
index 4788946d7fb25c1b0f26e6a038924c4a62978d53..82b25044e1852f5dbde1a658fe5f4f7526fa2b34 100644
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
@@ -826,6 +826,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
return true;
} catch (Exception exception) {
ChunkMap.LOGGER.error("Failed to save chunk {},{}", chunkcoordintpair.x, chunkcoordintpair.z, exception);
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper
return false;
}
}
diff --git a/src/main/java/net/minecraft/server/players/OldUsersConverter.java b/src/main/java/net/minecraft/server/players/OldUsersConverter.java
index b0ed7d12bee6b247762fff3d5a24f0cc9411e3dc..f6cb864c45f960811acc02829d1f7883b916de29 100644
--- a/src/main/java/net/minecraft/server/players/OldUsersConverter.java
+++ b/src/main/java/net/minecraft/server/players/OldUsersConverter.java
@@ -1,5 +1,6 @@
package net.minecraft.server.players;
+import com.destroystokyo.paper.exception.ServerInternalException;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.Files;
@@ -363,6 +364,7 @@ public class OldUsersConverter {
root = NbtIo.readCompressed(new java.io.FileInputStream(file5));
} catch (Exception exception) {
exception.printStackTrace();
+ ServerInternalException.reportInternalException(exception); // Paper
}
if (root != null) {
@@ -376,6 +378,7 @@ public class OldUsersConverter {
NbtIo.writeCompressed(root, new java.io.FileOutputStream(file2));
} catch (Exception exception) {
exception.printStackTrace();
+ ServerInternalException.reportInternalException(exception); // Paper
}
}
// CraftBukkit end
diff --git a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java
index 08c5f6fd1a307c89cf8365f56314a0c6d3e89e4b..26e0f03f2e736ed6ba86e2510a7962deee180ef3 100644
--- a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java
+++ b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java
@@ -1,5 +1,7 @@
package net.minecraft.world.entity.ai.village;
+import com.destroystokyo.paper.exception.ServerInternalException;
+
import java.util.Iterator;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
@@ -119,6 +121,7 @@ public class VillageSiege implements CustomSpawner {
entityzombie.finalizeSpawn(world, world.getCurrentDifficultyAt(entityzombie.blockPosition()), MobSpawnType.EVENT, (SpawnGroupData) null, (CompoundTag) null);
} catch (Exception exception) {
VillageSiege.LOGGER.warn("Failed to create zombie for village siege at {}", vec3d, exception);
+ ServerInternalException.reportInternalException(exception); // Paper
return;
}
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
index bc0adb68931c9c1404bf87a3f7643b4982e4ae35..33b20b43961051d2c116871ad63baa908fa71cd5 100644
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
@@ -1,5 +1,10 @@
package net.minecraft.world.level;
+import co.aikar.timings.Timing;
+import co.aikar.timings.Timings;
+import com.destroystokyo.paper.event.server.ServerExceptionEvent;
+import com.destroystokyo.paper.exception.ServerInternalException;
+import com.google.common.base.MoreObjects;
import com.google.common.collect.Lists;
import com.mojang.serialization.Codec;
import java.io.IOException;
@@ -736,6 +741,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
// Paper start - Prevent tile 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);
+ getCraftServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable)));
entity.discard();
// Paper end
}
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
index 808fd30d4b86ca9029c182ffdceaf27f3c204377..4ea02bfe348cec26bbb2c15ddacbbc110033b2d3 100644
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
@@ -308,6 +308,7 @@ public final class NaturalSpawner {
}
} catch (Exception exception) {
NaturalSpawner.LOGGER.warn("Failed to create mob", exception);
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper
return null;
}
}
@@ -410,6 +411,7 @@ public final class NaturalSpawner {
entity = biomesettingsmobs_c.type.create((Level) world.getLevel());
} catch (Exception exception) {
NaturalSpawner.LOGGER.warn("Failed to create mob", exception);
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper
continue;
}
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 ea894662b41cddfc5702a7d6305978be71da79b4..aa6db78339d6b0661ac3be12c82da92742b5f519 100644
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
@@ -1,6 +1,7 @@
package net.minecraft.world.level.chunk;
import com.google.common.collect.ImmutableList;
+import com.destroystokyo.paper.exception.ServerInternalException;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.collect.UnmodifiableIterator;
@@ -615,10 +616,15 @@ public class LevelChunk implements ChunkAccess {
this.removeBlockEntity(blockEntity.getBlockPos());
// Paper end
} else {
- System.out.println("Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + "," + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ()
- + " (" + this.getBlockState(blockposition) + ") where there was no entity tile!");
- System.out.println("Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16));
- new Exception().printStackTrace();
+ // Paper start
+ ServerInternalException e = new ServerInternalException(
+ "Attempted to place a tile entity (" + blockEntity + ") at " + blockEntity.getBlockPos().getX() + ","
+ + blockEntity.getBlockPos().getY() + "," + blockEntity.getBlockPos().getZ()
+ + " (" + getBlockState(blockposition) + ") where there was no entity tile!\n" +
+ "Chunk coordinates: " + (this.chunkPos.x * 16) + "," + (this.chunkPos.z * 16));
+ e.printStackTrace();
+ ServerInternalException.reportInternalException(e);
+ // Paper end
// CraftBukkit end
}
}
@@ -1250,6 +1256,7 @@ public class LevelChunk implements ChunkAccess {
// Paper start - Prevent tile 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);
+ net.minecraft.world.level.chunk.LevelChunk.this.level.getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new ServerInternalException(msg, throwable)));
LevelChunk.this.removeBlockEntity(this.getPos());
// Paper end
// Spigot start
diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
index 1441888430687b9de2a67f21ed426f16d5b30538..f514c29e64a9c7a66ff4edd5ba8c2a3dfbba2ad9 100644
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
@@ -277,6 +277,7 @@ public class RegionFile implements AutoCloseable {
return true;
}
} catch (IOException ioexception) {
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(ioexception); // Paper
return false;
}
}
@@ -358,6 +359,7 @@ public class RegionFile implements AutoCloseable {
((java.nio.Buffer) bytebuffer).position(5); // CraftBukkit - decompile error
filechannel.write(bytebuffer);
} catch (Throwable throwable) {
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper
if (filechannel != null) {
try {
filechannel.close();
diff --git a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java
index 2fdb313e8eaed868c36f68c9b7f6a6f9f4864575..c8ed0673ff819cb88d0ee6f53f2a2b9b46b203d4 100644
--- a/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java
+++ b/src/main/java/net/minecraft/world/level/storage/DimensionDataStorage.java
@@ -120,6 +120,7 @@ public class DimensionDataStorage {
pushbackInputStream.close();
} catch (Throwable var15) {
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(var15); // Paper
try {
fileInputStream.close();
} catch (Throwable var10) {
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
index 07c4d9cd5081378e1b903518f7174fca959cd9e3..dfc2789009fcaa08baa8054bdac915590b8701d6 100644
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
@@ -17,6 +17,9 @@ import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.IntUnaryOperator;
import java.util.logging.Level;
+import com.destroystokyo.paper.ServerSchedulerReportingWrapper;
+import com.destroystokyo.paper.event.server.ServerExceptionEvent;
+import com.destroystokyo.paper.exception.ServerSchedulerException;
import org.apache.commons.lang.Validate;
import org.bukkit.plugin.IllegalPluginAccessException;
import org.bukkit.plugin.Plugin;
@@ -434,6 +437,8 @@ public class CraftScheduler implements BukkitScheduler {
msg,
throwable);
}
+ org.bukkit.Bukkit.getServer().getPluginManager().callEvent(
+ new ServerExceptionEvent(new ServerSchedulerException(msg, throwable, task)));
// Paper end
} finally {
this.currentTask = null;
@@ -441,7 +446,7 @@ public class CraftScheduler implements BukkitScheduler {
this.parsePending();
} else {
this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass()));
- this.executor.execute(task);
+ this.executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper
// We don't need to parse pending
// (async tasks must live with race-conditions if they attempt to cancel between these few lines of code)
}