From cf0ff7252462fc7ff2b732b48dae2d7b560d3bd2 Mon Sep 17 00:00:00 2001 From: dordsor21 Date: Thu, 8 Oct 2020 10:53:57 +0100 Subject: [PATCH] Correctly queue edits Synchronising on the LocalSession ends up being dangerous as it's a craftbukkit thread, leading to blocking issues if something goes wrong in an edit, made worse by the fact craftbukkit threads like to interfere with each other sometimes, and also cause OOMs and hanging when there are too many of them. --- .../worldedit/extension/platform/AbstractPlayerActor.java | 4 ++-- .../com/sk89q/worldedit/extension/platform/Actor.java | 8 ++++---- .../extension/platform/PlatformCommandManager.java | 5 ++--- .../worldedit/extension/platform/PlatformManager.java | 4 ++-- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java index d180ef31a..b61589c33 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/AbstractPlayerActor.java @@ -79,8 +79,8 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable { private final Map meta; // Queue for async tasks - private AtomicInteger runningCount = new AtomicInteger(); - private AsyncNotifyQueue asyncNotifyQueue = new AsyncNotifyQueue( + private final AtomicInteger runningCount = new AtomicInteger(); + private final AsyncNotifyQueue asyncNotifyQueue = new AsyncNotifyQueue( (thread, throwable) -> { while (throwable.getCause() != null) { throwable = throwable.getCause(); diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java index 7761aaf9f..5a222f0cf 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/Actor.java @@ -189,11 +189,11 @@ public interface Actor extends Identifiable, SessionOwner, Subject, MapMetadatab */ default boolean confirm() { InterruptableCondition confirm = deleteMeta("cmdConfirm"); - if (confirm != null) { - confirm.signal();; - return true; + if (confirm == null) { + return false; } - return false; + queueAction(confirm::signal); + return true; } /** diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java index 22cd184ef..c8f0c099a 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformCommandManager.java @@ -652,13 +652,12 @@ public final class PlatformCommandManager { } else { actor.decline(); } - LocalSession session = worldEdit.getSessionManager().get(actor); - synchronized (session) { + actor.runAction(() -> { SessionKey key = actor.getSessionKey(); if (key.isActive()) { PlatformCommandManager.this.handleCommandOnCurrentThread(event); } - } + }, false, true); }, Fawe.isMainThread()); } diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java index 762c462d4..62910011c 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/extension/platform/PlatformManager.java @@ -437,7 +437,7 @@ public class PlatformManager { Tool tool = session.getTool(player); if (tool instanceof DoubleActionTraceTool && tool.canUse(player)) { player.runAsyncIfFree(() -> reset((DoubleActionTraceTool) tool).actSecondary(queryCapability(Capability.WORLD_EDITING), - getConfiguration(), player, session)); + getConfiguration(), player, session)); event.setCancelled(true); return; } @@ -450,7 +450,7 @@ public class PlatformManager { if (tool instanceof TraceTool && tool.canUse(player)) { //todo this needs to be fixed so the event is canceled after actPrimary is used and returns true player.runAction(() -> reset((TraceTool) tool).actPrimary(queryCapability(Capability.WORLD_EDITING), - getConfiguration(), player, session), false, true); + getConfiguration(), player, session), false, true); event.setCancelled(true); return; }