From bca2d92f77791af3785ec2dcaf494f7c55eb152b Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 11 Oct 2023 11:05:30 +0100 Subject: [PATCH 1/3] fix: clear player's history away from main thread if lock locked - addresses crashing of #2448 --- .../main/java/com/sk89q/worldedit/LocalSession.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index 3391bad80c..79ee2879b0 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -33,6 +33,7 @@ import com.fastasyncworldedit.core.util.BrushCache; import com.fastasyncworldedit.core.util.MainUtil; import com.fastasyncworldedit.core.util.StringMan; +import com.fastasyncworldedit.core.util.TaskManager; import com.fastasyncworldedit.core.util.TextureHolder; import com.fastasyncworldedit.core.util.TextureUtil; import com.fastasyncworldedit.core.wrappers.WorldWrapper; @@ -405,6 +406,15 @@ public void setTimezone(ZoneId timezone) { */ public void clearHistory() { //FAWE start + if (Fawe.isMainThread() && !historyWriteLock.tryLock()) { + // Do not make main thread wait if we cannot immediately clear history (on player logout usually) + TaskManager.taskManager().async(this::clearHistoryTask); + return; + } + clearHistoryTask(); + } + + private void clearHistoryTask() { historyWriteLock.lock(); try { // Ensure that changesets are properly removed @@ -420,8 +430,8 @@ public void clearHistory() { save(); historySize = 0; currentWorld = null; - //FAWE end } + //FAWE end /** * Remember an edit session for the undo history. If the history maximum From 2142257f3c72b20511e63431be21590d005dd37a Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 11 Oct 2023 16:53:44 +0100 Subject: [PATCH 2/3] Correct lock usage --- .../src/main/java/com/sk89q/worldedit/LocalSession.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index 79ee2879b0..62eb450506 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -144,7 +144,7 @@ public Object remove(int index) { } }); private transient volatile Integer historyNegativeIndex; - private transient final Lock historyWriteLock = new ReentrantLock(true); + private transient final ReentrantLock historyWriteLock = new ReentrantLock(true); private final transient Int2ObjectOpenHashMap tools = new Int2ObjectOpenHashMap<>(0); private transient Mask sourceMask; private transient TextureUtil texture; @@ -406,7 +406,7 @@ public void setTimezone(ZoneId timezone) { */ public void clearHistory() { //FAWE start - if (Fawe.isMainThread() && !historyWriteLock.tryLock()) { + if (Fawe.isMainThread() && historyWriteLock.isLocked()) { // Do not make main thread wait if we cannot immediately clear history (on player logout usually) TaskManager.taskManager().async(this::clearHistoryTask); return; From 14804a00e0fe1d105ec8d3b84c83856976780245 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Wed, 11 Oct 2023 18:50:25 +0100 Subject: [PATCH 3/3] remove possibility for race condition --- .../src/main/java/com/sk89q/worldedit/LocalSession.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java index 62eb450506..ae62a4f73b 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java @@ -406,12 +406,16 @@ public void setTimezone(ZoneId timezone) { */ public void clearHistory() { //FAWE start - if (Fawe.isMainThread() && historyWriteLock.isLocked()) { + if (Fawe.isMainThread() && !historyWriteLock.tryLock()) { // Do not make main thread wait if we cannot immediately clear history (on player logout usually) TaskManager.taskManager().async(this::clearHistoryTask); return; } - clearHistoryTask(); + try { + clearHistoryTask(); + } finally { + historyWriteLock.unlock(); + } } private void clearHistoryTask() {