2021-06-11 14:02:28 +02:00
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/players/OldUsersConverter.java b/src/main/java/net/minecraft/server/players/OldUsersConverter.java
2024-04-24 03:25:14 +02:00
index 68551947f5b7d3471f15bd74ccd86519ab34c1c1..a0b0614ac7d2009db5c6c10ab4a5f09dd447c635 100644
2021-06-11 14:02:28 +02:00
--- a/src/main/java/net/minecraft/server/players/OldUsersConverter.java
+++ b/src/main/java/net/minecraft/server/players/OldUsersConverter.java
2024-04-24 03:25:14 +02:00
@@ -356,7 +356,11 @@ public class OldUsersConverter {
try {
2023-12-05 20:54:55 +01:00
root = NbtIo.readCompressed(new java.io.FileInputStream(file5), NbtAccounter.unlimitedHeap());
2021-06-11 14:02:28 +02:00
} catch (Exception exception) {
2024-04-24 03:25:14 +02:00
- io.papermc.paper.util.TraceUtil.printStackTrace(exception); // Paper
+ // Paper start
+ io.papermc.paper.util.StacktraceDeobfuscator.INSTANCE.deobfuscateThrowable(exception);
+ exception.printStackTrace();
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception);
+ // Paper end
2021-06-11 14:02:28 +02:00
}
if (root != null) {
2024-04-24 03:25:14 +02:00
@@ -369,7 +373,11 @@ public class OldUsersConverter {
try {
2021-06-11 14:02:28 +02:00
NbtIo.writeCompressed(root, new java.io.FileOutputStream(file2));
} catch (Exception exception) {
2024-04-24 03:25:14 +02:00
- io.papermc.paper.util.TraceUtil.printStackTrace(exception); // Paper
+ // Paper start
+ io.papermc.paper.util.StacktraceDeobfuscator.INSTANCE.deobfuscateThrowable(exception);
+ exception.printStackTrace();
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception);
+ // Paper end
2021-06-11 14:02:28 +02:00
}
}
// 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
2024-04-24 03:25:14 +02:00
index 8183c26b4a5ad169a53702b8c45fd05cda934e80..36dec6cd78a0990ba3c09a4a748c259ef5c0a2ff 100644
2021-06-11 14:02:28 +02:00
--- a/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java
+++ b/src/main/java/net/minecraft/world/entity/ai/village/VillageSiege.java
2024-04-24 03:25:14 +02:00
@@ -117,6 +117,7 @@ public class VillageSiege implements CustomSpawner {
entityzombie.finalizeSpawn(world, world.getCurrentDifficultyAt(entityzombie.blockPosition()), MobSpawnType.EVENT, (SpawnGroupData) null);
2021-06-11 14:02:28 +02:00
} catch (Exception exception) {
VillageSiege.LOGGER.warn("Failed to create zombie for village siege at {}", vec3d, exception);
2024-01-23 14:34:17 +01:00
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper - ServerExceptionEvent
2021-06-11 14:02:28 +02:00
return;
}
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
2024-07-18 16:50:16 +02:00
index b4293991dddc9039c26106ac8c047e5aeec35a56..32b42d25631aecdd31db4954a8bbf38bcda98d6b 100644
2021-06-11 14:02:28 +02:00
--- a/src/main/java/net/minecraft/world/level/Level.java
+++ b/src/main/java/net/minecraft/world/level/Level.java
2024-06-13 19:30:39 +02:00
@@ -733,6 +733,7 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
2024-01-24 11:45:17 +01:00
// Paper start - Prevent block entity and entity crashes
2023-06-07 23:46:56 +02:00
final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level().getWorld().getName(), entity.getX(), entity.getY(), entity.getZ());
2021-06-21 10:09:18 +02:00
MinecraftServer.LOGGER.error(msg, throwable);
2024-02-01 10:15:57 +01:00
+ getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, throwable))); // Paper - ServerExceptionEvent
Updated Upstream (Bukkit/CraftBukkit/Spigot) (#10277)
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:
9a80d38c SPIGOT-336, SPIGOT-3366, SPIGOT-5768, SPIGOT-6409, SPIGOT-6861, PR-722: Add EntityRemoveEvent
258086d9 SPIGOT-7417, PR-967: Add Sign#getTargetSide and Sign#getAllowedEditor
ffaba051 SPIGOT-7584: Add missing Tag.ITEMS_NON_FLAMMABLE_WOOD
CraftBukkit Changes:
98b6c1ac7 SPIGOT-7589 Fix NullPointerException when bans expire
a2736ddb0 SPIGOT-336, SPIGOT-3366, SPIGOT-5768, SPIGOT-6409, SPIGOT-6861, PR-1008: Add EntityRemoveEvent
5bf12cb89 SPIGOT-7565: Throw a more descriptive error message when a developer tries to spawn an entity from a CraftBukkit class
76d95fe7e SPIGOT-7417, PR-1343: Add Sign#getTargetSide and Sign#getAllowedEditor
Spigot Changes:
e9ec5485 Rebuild patches
f1b62e0c Rebuild patches
2024-02-23 14:37:33 +01:00
entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD);
2024-01-24 11:45:17 +01:00
// Paper end - Prevent block entity and entity crashes
2021-06-12 02:57:04 +02:00
}
2021-06-11 14:02:28 +02:00
diff --git a/src/main/java/net/minecraft/world/level/NaturalSpawner.java b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
2024-04-24 03:25:14 +02:00
index 6a80479554f0c860a8dd6baa1a6506858fca83e3..6324689f52363f19501143c1649f0885684cb796 100644
2021-06-11 14:02:28 +02:00
--- a/src/main/java/net/minecraft/world/level/NaturalSpawner.java
+++ b/src/main/java/net/minecraft/world/level/NaturalSpawner.java
2024-04-24 03:25:14 +02:00
@@ -274,6 +274,7 @@ public final class NaturalSpawner {
2022-12-07 19:32:25 +01:00
NaturalSpawner.LOGGER.warn("Can't spawn entity of type: {}", BuiltInRegistries.ENTITY_TYPE.getKey(type));
2021-06-11 14:02:28 +02:00
} catch (Exception exception) {
NaturalSpawner.LOGGER.warn("Failed to create mob", exception);
2024-01-23 14:34:17 +01:00
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper - ServerExceptionEvent
2021-06-11 14:02:28 +02:00
}
2022-12-07 19:32:25 +01:00
return null;
2024-04-24 03:25:14 +02:00
@@ -362,6 +363,7 @@ public final class NaturalSpawner {
2021-11-23 13:15:10 +01:00
entity = biomesettingsmobs_c.type.create(world.getLevel());
2021-06-12 02:57:04 +02:00
} catch (Exception exception) {
NaturalSpawner.LOGGER.warn("Failed to create mob", exception);
2024-01-23 14:34:17 +01:00
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper - ServerExceptionEvent
2021-06-12 02:57:04 +02:00
continue;
}
2021-06-11 14:02:28 +02:00
diff --git a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
2024-06-19 19:29:03 +02:00
index 7bfe757b605f4e5a16b28214ac3b497e738b45b5..fb953b2172c322e8abf5aa50060adbc00fe92832 100644
2021-06-11 14:02:28 +02:00
--- a/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/src/main/java/net/minecraft/world/level/chunk/LevelChunk.java
2024-06-19 19:29:03 +02:00
@@ -466,8 +466,13 @@ public class LevelChunk extends ChunkAccess {
2024-06-13 19:30:39 +02:00
BlockState iblockdata = this.getBlockState(blockposition);
2021-06-11 14:02:28 +02:00
2024-06-13 19:30:39 +02:00
if (!iblockdata.hasBlockEntity()) {
- LevelChunk.LOGGER.warn("Trying to set block entity {} at position {}, but state {} does not allow it", new Object[]{blockEntity, blockposition, iblockdata});
- new Exception().printStackTrace(); // CraftBukkit
2024-01-23 14:34:17 +01:00
+ // Paper start - ServerExceptionEvent
2024-06-13 19:30:39 +02:00
+ com.destroystokyo.paper.exception.ServerInternalException e = new com.destroystokyo.paper.exception.ServerInternalException(
+ "Trying to set block entity %s at position %s, but state %s does not allow it".formatted(blockEntity, blockposition, iblockdata)
+ );
2021-06-11 14:02:28 +02:00
+ e.printStackTrace();
2024-06-13 19:30:39 +02:00
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(e);
2024-01-23 14:34:17 +01:00
+ // Paper end - ServerExceptionEvent
2024-06-13 19:30:39 +02:00
} else {
BlockState iblockdata1 = blockEntity.getBlockState();
2024-06-19 19:29:03 +02:00
@@ -951,6 +956,7 @@ public class LevelChunk extends ChunkAccess {
2024-01-24 11:45:17 +01:00
// Paper start - Prevent block entity and entity crashes
2021-06-21 10:09:18 +02:00
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);
2024-06-14 14:11:52 +02:00
+ net.minecraft.world.level.chunk.LevelChunk.this.level.getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, throwable))); // Paper - ServerExceptionEvent
2021-06-12 02:57:04 +02:00
LevelChunk.this.removeBlockEntity(this.getPos());
2024-01-24 11:45:17 +01:00
// Paper end - Prevent block entity and entity crashes
2021-06-12 02:57:04 +02:00
// Spigot start
2021-06-11 14:02:28 +02:00
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
2024-04-24 03:25:14 +02:00
index 15f273aa592828719de6e092d79a407dc8652dfe..b24e8255ab18eb5b2e4968aa62aa3d72ef33f0eb 100644
2021-06-11 14:02:28 +02:00
--- a/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
+++ b/src/main/java/net/minecraft/world/level/chunk/storage/RegionFile.java
2024-04-24 03:25:14 +02:00
@@ -296,6 +296,7 @@ public class RegionFile implements AutoCloseable {
2021-06-11 14:02:28 +02:00
return true;
}
} catch (IOException ioexception) {
2024-01-23 14:34:17 +01:00
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(ioexception); // Paper - ServerExceptionEvent
2021-06-11 14:02:28 +02:00
return false;
}
}
2024-04-24 03:25:14 +02:00
@@ -377,6 +378,7 @@ public class RegionFile implements AutoCloseable {
2022-11-12 21:57:41 +01:00
((java.nio.Buffer) buf).position(5); // CraftBukkit - decompile error
filechannel.write(buf);
2021-06-12 02:57:04 +02:00
} catch (Throwable throwable) {
2024-01-23 14:34:17 +01:00
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper - ServerExceptionEvent
2021-06-11 14:02:28 +02:00
if (filechannel != null) {
2021-06-12 02:57:04 +02:00
try {
filechannel.close();
2021-06-11 14:02:28 +02:00
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
2024-07-18 16:50:16 +02:00
index 6c0debe3f3b693ed90dd2a39f481cccd8e4f7634..cf9f04e005940f5dd7baf50435f3703fa7c2d4f0 100644
2021-06-11 14:02:28 +02:00
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
2024-07-18 16:50:16 +02:00
@@ -416,20 +416,25 @@ public class CraftScheduler implements BukkitScheduler {
try {
task.run();
} catch (final Throwable throwable) {
+ // Paper start
+ final String logMessage = String.format(
+ "Task #%s for %s generated an exception",
+ task.getTaskId(),
+ task.getOwner().getDescription().getFullName());
task.getOwner().getLogger().log(
Level.WARNING,
- String.format(
- "Task #%s for %s generated an exception",
- task.getTaskId(),
- task.getOwner().getDescription().getFullName()),
+ logMessage,
2021-06-11 14:02:28 +02:00
throwable);
+ org.bukkit.Bukkit.getServer().getPluginManager().callEvent(
2024-07-18 16:50:16 +02:00
+ new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerSchedulerException(logMessage, throwable, task)));
+ // Paper end
2021-06-11 14:02:28 +02:00
} finally {
2021-06-12 02:57:04 +02:00
this.currentTask = null;
2024-07-18 16:50:16 +02:00
}
2021-06-12 02:57:04 +02:00
this.parsePending();
2021-06-11 14:02:28 +02:00
} else {
2021-06-12 02:57:04 +02:00
this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass()));
- this.executor.execute(task);
2023-06-13 01:51:45 +02:00
+ this.executor.execute(new com.destroystokyo.paper.ServerSchedulerReportingWrapper(task)); // Paper
2021-06-11 14:02:28 +02:00
// 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)
}