This also cleans up the implementation of Async Chunks to get rid of most Consumer callbacks and instead return futures. This lets us propogate errors correctly up the future chain (barring one isn't lost even deeper in the chain...) So exceptions can now bubble to plugins using getChunkAtAsync
61 lines
3.3 KiB
Diff
61 lines
3.3 KiB
Diff
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 edf0cf3680e5d2212f35c9d4464b22e0f3e87342..c3528212ae1bfbdbe6910bcd775990b9b638afaf 100644
|
|
--- a/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
+++ b/src/main/java/net/minecraft/server/ChunkProviderServer.java
|
|
@@ -1051,6 +1051,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 6c178492b75134ba25b7730273bb550b693a7e4a..79133dd40c465224b1dfa2afaf4c8d3f5a1c2190 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
@@ -108,6 +108,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<>();
|
|
|
|
@@ -974,7 +976,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
return Either.left(chunk);
|
|
});
|
|
}, (runnable) -> {
|
|
- this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, runnable)); // CraftBukkit - decompile error
|
|
+ this.mailboxMain.a(ChunkTaskQueueSorter.a(playerchunk, () -> PlayerChunkMap.this.chunkLoadConversionCallbackExecutor.execute(runnable))); // CraftBukkit - decompile error // 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) -> {
|