aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/1017-Detail-more-information-in-watchdog-dumps.patch
blob: 710f25f69b0f3f7a3a4766788a5782bb97a510f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Spottedleaf <Spottedleaf@users.noreply.github.com>
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 fff375fd50fa1a804636a92ded1ae55cff42977d..4716f8bd8a64d4f20f0d5957c1e7fabf63020f43 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -586,7 +586,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 { // Paper end - detailed watchdog information
             tickablepacketlistener.tick();
+            } finally { // Paper start - detailed watchdog information
+                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 454d0187ff8370a0d99cca051ee0a8c50b39cfb7..3e2d5dcd62775b6ed7c0ce0ba51a71b635b1d644 100644
--- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java
+++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
@@ -18,6 +18,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 {
@@ -27,6 +45,8 @@ public class PacketUtils {
     public static <T extends PacketListener> void ensureRunningOnSameThread(Packet<T> packet, T listener, BlockableEventLoop<?> engine) throws RunningOnDifferentThreadException {
         if (!engine.isSameThread()) {
             engine.execute(() -> { // Paper - Fix preemptive player kick on a server shutdown
+                packetProcessing.push(listener); // Paper - detailed watchdog information
+                try { // Paper - detailed watchdog information
                 if (MinecraftServer.getServer().hasStopped() || (listener instanceof ServerCommonPacketListenerImpl && ((ServerCommonPacketListenerImpl) listener).processedDisconnect)) return; // CraftBukkit, MC-142590
                 if (listener.shouldHandleMessage(packet)) {
                     co.aikar.timings.Timing timing = co.aikar.timings.MinecraftTimings.getPacketTiming(packet); // Paper - timings
@@ -64,6 +84,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 9d18da228c6709e7665ba8babb6ee6d0b36b5dc5..af9f58328c09dddb2875f79128f906b8b276ab88 100644
--- a/src/main/java/net/minecraft/server/level/ServerLevel.java
+++ b/src/main/java/net/minecraft/server/level/ServerLevel.java
@@ -1239,7 +1239,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
@@ -1279,7 +1298,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 28ca0aae8f8c755b558a03fc9283fa1a44697e1a..ec01a97cac653fb1a2065289fe5b0c6824732bcb 100644
--- a/src/main/java/net/minecraft/world/entity/Entity.java
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
@@ -1063,8 +1063,43 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
         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) {
         final Vec3 originalMovement = movement; // Paper - Expose pre-collision velocity
+        // 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 {
@@ -1234,6 +1269,13 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
                 this.level().getProfiler().pop();
             }
         }
+        // Paper start - detailed watchdog information
+        } finally {
+            synchronized (this.posLock) { // Paper
+                this.moveVector = null;
+            } // Paper
+        }
+        // Paper end - detailed watchdog information
     }
 
     private boolean isStateClimbable(BlockState state) {
@@ -4379,7 +4421,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
     }
 
     public void setDeltaMovement(Vec3 velocity) {
+        synchronized (this.posLock) { // Paper
         this.deltaMovement = velocity;
+        } // Paper
     }
 
     public void addDeltaMovement(Vec3 velocity) {
@@ -4482,7 +4526,9 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S
         }
         // 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 0234555978d1b13051f876a257e47bafad37b0f8..9e638f72f180ff5ef63ec3dd6cf548c53f7bd4a5 100644
--- a/src/main/java/org/spigotmc/WatchdogThread.java
+++ b/src/main/java/org/spigotmc/WatchdogThread.java
@@ -22,6 +22,78 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
     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" );
@@ -119,6 +191,7 @@ public final class WatchdogThread extends io.papermc.paper.util.TickThread // Pa
                 log.log( Level.SEVERE, "------------------------------" );
                 log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); // Paper
                 io.papermc.paper.chunk.system.scheduling.ChunkTaskScheduler.dumpAllChunkLoadInfo(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, "------------------------------" );
                 //