aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0397-Fix-Chunk-Post-Processing-deadlock-risk.patch
diff options
context:
space:
mode:
authorJake Potrebic <[email protected]>2022-03-30 13:28:38 -0700
committerGitHub <[email protected]>2022-03-30 13:28:38 -0700
commit7f47b9b7f84f9bee31b3e046a8dcbd28ec012fe0 (patch)
tree08dd0cadd782982719e33315c2ae5687b2ce21fb /patches/server/0397-Fix-Chunk-Post-Processing-deadlock-risk.patch
parentd3c102373f90cffa1be2a19ce671d99d563ff9ca (diff)
downloadPaper-7f47b9b7f84f9bee31b3e046a8dcbd28ec012fe0.tar.gz
Paper-7f47b9b7f84f9bee31b3e046a8dcbd28ec012fe0.zip
Remove KeyedObject interface (#7680)
Diffstat (limited to 'patches/server/0397-Fix-Chunk-Post-Processing-deadlock-risk.patch')
-rw-r--r--patches/server/0397-Fix-Chunk-Post-Processing-deadlock-risk.patch73
1 files changed, 73 insertions, 0 deletions
diff --git a/patches/server/0397-Fix-Chunk-Post-Processing-deadlock-risk.patch b/patches/server/0397-Fix-Chunk-Post-Processing-deadlock-risk.patch
new file mode 100644
index 0000000000..240ccc2344
--- /dev/null
+++ b/patches/server/0397-Fix-Chunk-Post-Processing-deadlock-risk.patch
@@ -0,0 +1,73 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Aikar <[email protected]>
+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 boundaries 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 reproducible crash
+for heightmaps.
+
+diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
+index 7776c22744cdd31459e9634d1d549bdf2876e04f..43e5e148f1289ff5e42311981c597c66d98447aa 100644
+--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
++++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
+@@ -178,6 +178,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+ };
+ // CraftBukkit end
+
++ final CallbackExecutor chunkLoadConversionCallbackExecutor = new CallbackExecutor(); // Paper
+ // Paper start - distance maps
+ private final com.destroystokyo.paper.util.misc.PooledLinkedHashSets<ServerPlayer> pooledLinkedPlayerHashSets = new com.destroystokyo.paper.util.misc.PooledLinkedHashSets<>();
+
+@@ -995,16 +996,15 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
+ });
+ CompletableFuture<Either<LevelChunk, ChunkHolder.ChunkLoadingFailure>> completablefuture1 = completablefuture.thenApplyAsync((either) -> {
+ return either.mapLeft((list) -> {
+- return (LevelChunk) list.get(list.size() / 2);
+- });
+- }, (runnable) -> {
+- this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, runnable));
+- }).thenApplyAsync((either) -> {
+- return either.ifLeft((chunk) -> {
++ // Paper start - revert 1.18.2 diff
++ final LevelChunk chunk = (LevelChunk) list.get(list.size() / 2);
+ chunk.postProcessGeneration();
+ this.level.startTickingChunk(chunk);
++ return chunk;
+ });
+- }, this.mainThreadExecutor);
++ }, (runnable) -> {
++ this.mainThreadMailbox.tell(ChunkTaskPriorityQueueSorter.message(holder, () -> ChunkMap.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.
++ }); // Paper end - revert 1.18.2 diff
+
+ completablefuture1.thenAcceptAsync((either) -> {
+ either.ifLeft((chunk) -> {
+diff --git a/src/main/java/net/minecraft/server/level/ServerChunkCache.java b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+index 8f1609bbb5670d3b4acccb2cb4b9238ce13290bb..cf5a5d98420c3849621bfdfae7bda7d5cb4b2dc9 100644
+--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
++++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
+@@ -1133,6 +1133,7 @@ public class ServerChunkCache extends ChunkSource {
+ return super.pollTask() || execChunkTask; // Paper
+ }
+ } finally {
++ chunkMap.chunkLoadConversionCallbackExecutor.run(); // Paper - Add chunk load conversion callback executor to prevent deadlock due to recursion in the chunk task queue sorter
+ chunkMap.callbackExecutor.run();
+ }
+ // CraftBukkit end