aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0739-Detail-more-information-in-watchdog-dumps.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patches/server/0739-Detail-more-information-in-watchdog-dumps.patch')
-rw-r--r--patches/server/0739-Detail-more-information-in-watchdog-dumps.patch297
1 files changed, 297 insertions, 0 deletions
diff --git a/patches/server/0739-Detail-more-information-in-watchdog-dumps.patch b/patches/server/0739-Detail-more-information-in-watchdog-dumps.patch
new file mode 100644
index 0000000000..0fc0b9475e
--- /dev/null
+++ b/patches/server/0739-Detail-more-information-in-watchdog-dumps.patch
@@ -0,0 +1,297 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Spottedleaf <[email protected]>
+Date: Thu, 26 Mar 2020 21:59:32 -0700
+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 057a0be81b12bd8a4ac71106dc8ada91bd4c9bfd..98443474d1881bbeee8f249b89e44a0f84261be7 100644
+--- a/src/main/java/net/minecraft/network/Connection.java
++++ b/src/main/java/net/minecraft/network/Connection.java
+@@ -475,9 +475,15 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+ PacketListener packetlistener = this.packetListener;
+
+ if (packetlistener instanceof TickablePacketListener) {
++ // Paper start - detailed watchdog information
++ net.minecraft.network.protocol.PacketUtils.packetProcessing.push(this.packetListener);
++ try { // Paper end - detailed watchdog information
+ TickablePacketListener tickablepacketlistener = (TickablePacketListener) packetlistener;
+
+ tickablepacketlistener.tick();
++ } finally { // Paper start - detailed watchdog information
++ net.minecraft.network.protocol.PacketUtils.packetProcessing.pop();
++ } // Paper start - detailed watchdog information
+ }
+
+ if (!this.isConnected() && !this.disconnectionHandled) {
+diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
+index acfa1907bfc9c29d261cfccc00d65bad9ad1a002..d6f3869f5725c7f081efb7f486f74dbb99d4d005 100644
+--- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java
++++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
+@@ -15,6 +15,24 @@ public class PacketUtils {
+
+ private static final Logger LOGGER = LogUtils.getLogger();
+
++ // 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();
++
++ public static long getTotalProcessedPackets() {
++ return totalMainThreadPacketsProcessed.get();
++ }
++
++ public static java.util.List<PacketListener> getCurrentPacketProcessors() {
++ java.util.List<PacketListener> ret = new java.util.ArrayList<>(4);
++ for (PacketListener listener : packetProcessing) {
++ ret.add(listener);
++ }
++
++ return ret;
++ }
++ // Paper end - detailed watchdog information
++
+ public PacketUtils() {}
+
+ public static <T extends PacketListener> void ensureRunningOnSameThread(Packet<T> packet, T listener, ServerLevel world) throws RunningOnDifferentThreadException {
+@@ -24,6 +42,8 @@ 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 (MinecraftServer.getServer().hasStopped() || (listener instanceof ServerGamePacketListenerImpl && ((ServerGamePacketListenerImpl) listener).processedDisconnect)) return; // CraftBukkit, MC-142590
+ if (listener.getConnection().isConnected()) {
+ co.aikar.timings.Timing timing = co.aikar.timings.MinecraftTimings.getPacketTiming(packet); // Paper - timings
+@@ -43,6 +63,12 @@ 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 7324f2ad437a15c42f84ba2deeb58861c0552209..92aafd475d58d1ef2e2736d9363c4b1010724fd7 100644
+--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
+@@ -1006,7 +1006,26 @@ public class ServerLevel extends Level implements WorldGenLevel {
+
+ }
+
++ // Paper start - log detailed entity tick information
++ // TODO replace with varhandle
++ static final java.util.concurrent.atomic.AtomicReference<Entity> currentlyTickingEntity = new java.util.concurrent.atomic.AtomicReference<>();
++
++ public static List<Entity> getCurrentlyTickingEntities() {
++ Entity ticking = currentlyTickingEntity.get();
++ List<Entity> ret = java.util.Arrays.asList(ticking == null ? new Entity[0] : new Entity[] { ticking });
++
++ return ret;
++ }
++ // Paper end - log detailed entity tick information
++
+ public void tickNonPassenger(Entity entity) {
++ // Paper start - log detailed entity tick information
++ io.papermc.paper.util.TickThread.ensureTickThread("Cannot tick an entity off-main");
++ try {
++ if (currentlyTickingEntity.get() == null) {
++ currentlyTickingEntity.lazySet(entity);
++ }
++ // Paper end - log detailed entity tick information
+ ++TimingHistory.entityTicks; // Paper - timings
+ // Spigot start
+ co.aikar.timings.Timing timer; // Paper
+@@ -1046,7 +1065,13 @@ public class ServerLevel extends Level implements WorldGenLevel {
+ this.tickPassenger(entity, entity1);
+ }
+ // } finally { timer.stopTiming(); } // Paper - timings - move up
+-
++ // Paper start - log detailed entity tick information
++ } finally {
++ if (currentlyTickingEntity.get() == entity) {
++ currentlyTickingEntity.lazySet(null);
++ }
++ }
++ // Paper end - log detailed entity tick information
+ }
+
+ private void tickPassenger(Entity vehicle, Entity passenger) {
+diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
+index f8458173dd717ca5fd9d265dcdaee0f0ef1a833c..51239bc47d6d2cfd8d345fb67fe0d92fabe53209 100644
+--- a/src/main/java/net/minecraft/world/entity/Entity.java
++++ b/src/main/java/net/minecraft/world/entity/Entity.java
+@@ -971,7 +971,42 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+ return this.onGround;
+ }
+
++ // Paper start - detailed watchdog information
++ public final Object posLock = new Object(); // Paper - log detailed entity tick information
++
++ private Vec3 moveVector;
++ private double moveStartX;
++ private double moveStartY;
++ private double moveStartZ;
++
++ public final Vec3 getMoveVector() {
++ return this.moveVector;
++ }
++
++ public final double getMoveStartX() {
++ return this.moveStartX;
++ }
++
++ public final double getMoveStartY() {
++ return this.moveStartY;
++ }
++
++ public final double getMoveStartZ() {
++ return this.moveStartZ;
++ }
++ // Paper end - detailed watchdog information
++
+ public void move(MoverType movementType, Vec3 movement) {
++ // Paper start - detailed watchdog information
++ io.papermc.paper.util.TickThread.ensureTickThread("Cannot move an entity off-main");
++ synchronized (this.posLock) {
++ this.moveStartX = this.getX();
++ this.moveStartY = this.getY();
++ this.moveStartZ = this.getZ();
++ this.moveVector = movement;
++ }
++ try {
++ // Paper end - detailed watchdog information
+ if (this.noPhysics) {
+ this.setPos(this.getX() + movement.x, this.getY() + movement.y, this.getZ() + movement.z);
+ } else {
+@@ -1144,6 +1179,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+ this.level.getProfiler().pop();
+ }
+ }
++ // Paper start - detailed watchdog information
++ } finally {
++ synchronized (this.posLock) { // Paper
++ this.moveVector = null;
++ } // Paper
++ }
++ // Paper end - detailed watchdog information
+ }
+
+ protected boolean isHorizontalCollisionMinor(Vec3 adjustedMovement) {
+@@ -3962,7 +4004,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+ }
+
+ public void setDeltaMovement(Vec3 velocity) {
++ synchronized (this.posLock) { // Paper
+ this.deltaMovement = velocity;
++ } // Paper
+ }
+
+ public void setDeltaMovement(double x, double y, double z) {
+@@ -4038,7 +4082,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource {
+ }
+ // 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 7823e97add506d42161fd86f830e4d988b2113d8..d568fc92d03c313a782796cc720a1ebb1a5ad8be 100644
+--- a/src/main/java/org/spigotmc/WatchdogThread.java
++++ b/src/main/java/org/spigotmc/WatchdogThread.java
+@@ -22,6 +22,78 @@ public class WatchdogThread extends Thread
+ 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" );
+@@ -120,6 +192,7 @@ public class WatchdogThread extends Thread
+ log.log( Level.SEVERE, "------------------------------" );
+ log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper
+ com.destroystokyo.paper.io.chunk.ChunkTaskManager.dumpAllChunkLoadInfo(); // Paper
++ this.dumpTickingInfo(); // Paper - log detailed tick information
+ WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( server.serverThread.getId(), Integer.MAX_VALUE ), log );
+ log.log( Level.SEVERE, "------------------------------" );
+ //