aboutsummaryrefslogtreecommitdiffhomepage
path: root/Spigot-Server-Patches/0082-Ensure-commands-are-not-ran-async.patch
diff options
context:
space:
mode:
Diffstat (limited to 'Spigot-Server-Patches/0082-Ensure-commands-are-not-ran-async.patch')
-rw-r--r--Spigot-Server-Patches/0082-Ensure-commands-are-not-ran-async.patch86
1 files changed, 86 insertions, 0 deletions
diff --git a/Spigot-Server-Patches/0082-Ensure-commands-are-not-ran-async.patch b/Spigot-Server-Patches/0082-Ensure-commands-are-not-ran-async.patch
new file mode 100644
index 0000000000..06623de03f
--- /dev/null
+++ b/Spigot-Server-Patches/0082-Ensure-commands-are-not-ran-async.patch
@@ -0,0 +1,86 @@
+From e234b01e0a17f6930f80f9bbf9c481facb0bbaf3 Mon Sep 17 00:00:00 2001
+From: Aikar <[email protected]>
+Date: Wed, 8 Oct 2014 19:51:28 -0400
+Subject: [PATCH] Ensure commands are not ran async
+
+Plugins calling Player.chat("/foo") or Server.dispatchCommand() could
+trigger the server to execute a command while on another thread.
+
+These commands would then process EXPECTING to be on the main thread, leaving to
+very hard to trace concurrency issues.
+
+This change will synchronize the command execution back to the main thread, causing a
+big slowdown in execution but throwing an exception at same time to raise awareness
+that it is happening so that plugin authors can fix their code to stop executing commands async.
+
+diff --git a/src/main/java/net/minecraft/server/PlayerConnection.java b/src/main/java/net/minecraft/server/PlayerConnection.java
+index 1138042..4391ad7 100644
+--- a/src/main/java/net/minecraft/server/PlayerConnection.java
++++ b/src/main/java/net/minecraft/server/PlayerConnection.java
+@@ -1079,6 +1079,29 @@ public class PlayerConnection implements PacketListenerPlayIn, IUpdatePlayerList
+ }
+
+ if (!async && s.startsWith("/")) {
++ // PaperSpigot Start
++ if (!org.bukkit.Bukkit.isPrimaryThread()) {
++ final String fCommandLine = s;
++ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Command Dispatched Async: " + fCommandLine);
++ MinecraftServer.LOGGER.log(org.apache.logging.log4j.Level.ERROR, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable());
++ Waitable wait = new Waitable() {
++ @Override
++ protected Object evaluate() {
++ chat(fCommandLine, false);
++ return null;
++ }
++ };
++ minecraftServer.processQueue.add(wait);
++ try {
++ wait.get();
++ return;
++ } catch (InterruptedException e) {
++ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on!
++ } catch (Exception e) {
++ throw new RuntimeException("Exception processing chat command", e.getCause());
++ }
++ }
++ // PaperSpigot End
+ this.handleCommand(s);
+ } else if (this.player.getChatFlags() == EntityHuman.EnumChatVisibility.SYSTEM) {
+ // Do nothing, this is coming from a plugin
+diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+index 97f9f96..a54b3e8 100644
+--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+@@ -639,6 +639,29 @@ public final class CraftServer implements Server {
+ Validate.notNull(sender, "Sender cannot be null");
+ Validate.notNull(commandLine, "CommandLine cannot be null");
+
++ // PaperSpigot Start
++ if (!Bukkit.isPrimaryThread()) {
++ final CommandSender fSender = sender;
++ final String fCommandLine = commandLine;
++ Bukkit.getLogger().log(Level.SEVERE, "Command Dispatched Async: " + commandLine);
++ Bukkit.getLogger().log(Level.SEVERE, "Please notify author of plugin causing this execution to fix this bug! see: http://bit.ly/1oSiM6C", new Throwable());
++ org.bukkit.craftbukkit.util.Waitable<Boolean> wait = new org.bukkit.craftbukkit.util.Waitable<Boolean>() {
++ @Override
++ protected Boolean evaluate() {
++ return dispatchCommand(fSender, fCommandLine);
++ }
++ };
++ net.minecraft.server.MinecraftServer.getServer().processQueue.add(wait);
++ try {
++ return wait.get();
++ } catch (InterruptedException e) {
++ Thread.currentThread().interrupt(); // This is proper habit for java. If we aren't handling it, pass it on!
++ } catch (Exception e) {
++ throw new RuntimeException("Exception processing dispatch command", e.getCause());
++ }
++ }
++ // PaperSpigot End
++
+ if (commandMap.dispatch(sender, commandLine)) {
+ return true;
+ }
+--
+2.7.0
+