74 lines
4.0 KiB
Diff
74 lines
4.0 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 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 eb0fbf2126e7c9978f46c92b6999f00c5aea9a58..bfd0398e4bca5458d2913715b742b3c5a0b076f8 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
@@ -182,6 +182,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<>();
|
|
|
|
@@ -1021,16 +1022,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 4581a95a792e8eb157c8577547cb6f76a8e8f883..55b8f9dc3ad2b282e83c912ad8bf46b31cbd3765 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ServerChunkCache.java
|
|
@@ -1138,6 +1138,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
|