aboutsummaryrefslogtreecommitdiffhomepage
path: root/Spigot-Server-Patches/0459-Fix-Chunk-Post-Processing-deadlock-risk.patch
blob: 2aaf29124e895c0c5a637b65601fac9b376f0ebb (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
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Sat, 18 Apr 2020 04:36:11 -0400
Subject: [PATCH] Fix Chunk Post Processing deadlock risk

See: https://gist.github.com/aikar/dd22bbd2a3d78a2fd3d92e95e9f28dc6

as part of post processing a chunk, we can call ChunkConverter.

ChunkConverter then kicks off major physics updates, and when blocks
that have connections across chunk boundries occur, a recursive risk
can occur where A updates a block that triggers a physics request.

That physics request may trigger a chunk request, that then enqueues
a task into the Mailbox ChunkTaskQueueSorter.

If anything requests that same chunk that is in the middle of conversion,
it's mailbox queue is going to be held up, so the subsequent chunk request
will be unable to proceed.

We delay post processing of Chunk.A() 1 "pass" by re stuffing it back into
the executor so that the mailbox ChunkQueue is now considered empty.

This successfully fixed a reoccurring and highly reproduceable crash
for heightmaps.

diff --git a/src/main/java/net/minecraft/server/ChunkProviderServer.java b/src/main/java/net/minecraft/server/ChunkProviderServer.java
index 91755cd7313d87bae85584dff140acbc6467428f..0080a0cbe58d1a81c434ef97659428c8bf1ec290 100644
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
@@ -994,6 +994,7 @@ public class ChunkProviderServer extends IChunkProvider {
                 return super.executeNext() || execChunkTask; // Paper
             }
         } finally {
+            playerChunkMap.chunkLoadConversionCallbackExecutor.run(); // Paper - Add chunk load conversion callback executor to prevent deadlock due to recursion in the chunk task queue sorter
             playerChunkMap.callbackExecutor.run();
         }
         // CraftBukkit end
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
index 1fcf75b2ed3c8c1ca2e31f679fc7d507f963caf2..fbe7129280f371ab9658fba2965c003b455aaa7a 100644
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
@@ -133,6 +133,8 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
     };
     // CraftBukkit end
 
+    final CallbackExecutor chunkLoadConversionCallbackExecutor = new CallbackExecutor(); // Paper
+
     // Paper start - distance maps
     private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets<EntityPlayer> pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>();
 
@@ -998,7 +1000,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
                 return Either.left(chunk);
             });
         }, (runnable) -> {
-            this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, runnable));
+            this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, () -> PlayerChunkMap.this.chunkLoadConversionCallbackExecutor.execute(runnable))); // Paper - delay running Chunk post processing until outside of the sorter to prevent a deadlock scenario when post processing causes another chunk request.
         });
 
         completablefuture1.thenAcceptAsync((either) -> {