mirror of
https://github.com/PaperMC/Paper.git
synced 2024-12-29 07:48:53 +01:00
789bc79280
Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: c9a46ebf #653: Add World#spawn with randomizeData parameter e49c2e3a Damageable should extend ItemMeta 01ff04f4 SPIGOT-5880, SPIGOT-5567: New ChunkGenerator API ca5b4b1a SPIGOT-6697: Deprecate generateTree with BlockChangeDelegate as it does not handle tiles CraftBukkit Changes: 7c8bbcbe SPIGOT-6716: Preserve the order of stored enchantments of enchanted books. 18027d02 #914: Add World#spawn with randomizeData parameter 3cad0316 SPIGOT-6714: Don't fire PlayerBucketEvent when empty 8c6d60cf Fix server crash with BlockPopulator when entities are at a negative chunk border 4f6bcc84 SPIGOT-5880, SPIGOT-5567: New ChunkGenerator API 78d5b35b SPIGOT-6697: Restore generateTree with BlockChangeDelegate behaviour 15792f0d Rebuild patch c949675e SPIGOT-6713: Cancelling EntityTransformEvent Causes Deceased Slimes To Not Despawn a955f15c Fix issues with new ChunkGenerator API a0a37f41 SPIGOT-6630: Replacing an enchantment on an item creates a conflict error Spigot Changes: b166a49b Rebuild patches 3c1fc60a SPIGOT-6693: Composters only take in one item at custom hopper speeds
118 lines
6.4 KiB
Diff
118 lines
6.4 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
Date: Thu, 3 Mar 2016 01:17:12 -0600
|
|
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/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
index da9f4b3337b49597c17b50964656457cd629a0b7..22c2c121bbcc7b0e15d73d20c9cc83d5fb085e5f 100644
|
|
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
|
|
@@ -1846,6 +1846,29 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
|
|
}
|
|
|
|
if (!async && s.startsWith("/")) {
|
|
+ // Paper Start
|
|
+ if (!org.spigotmc.AsyncCatcher.shuttingDown && !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;
|
|
+ }
|
|
+ };
|
|
+ server.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());
|
|
+ }
|
|
+ }
|
|
+ // Paper End
|
|
this.handleCommand(s);
|
|
} else if (this.player.getChatVisibility() == ChatVisiblity.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 167558990f82c9b463377bbc64e18baa956871db..d8f5476067cb41d04ebccd690b83756b95396500 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
|
|
@@ -773,6 +773,28 @@ public final class CraftServer implements Server {
|
|
Validate.notNull(commandLine, "CommandLine cannot be null");
|
|
org.spigotmc.AsyncCatcher.catchOp("command dispatch"); // Spigot
|
|
|
|
+ // Paper Start
|
|
+ if (!org.spigotmc.AsyncCatcher.shuttingDown && !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());
|
|
+ }
|
|
+ }
|
|
+ // Paper End
|
|
if (this.commandMap.dispatch(sender, commandLine)) {
|
|
return true;
|
|
}
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java
|
|
index 19c44daaa407b7c1c7a7ffe56fef8c8814c6d5b2..6a073a9dc44d93eba296a0e18a9c7be8a7881725 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java
|
|
@@ -13,6 +13,7 @@ public class ServerShutdownThread extends Thread {
|
|
public void run() {
|
|
try {
|
|
org.spigotmc.AsyncCatcher.enabled = false; // Spigot
|
|
+ org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper
|
|
this.server.close();
|
|
} finally {
|
|
try {
|
|
diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java
|
|
index bbf0d9d9c44fe8d7add2f978994ec129420814c7..7a23b56752f6733ee626a8b1e4c3b78591855c4e 100644
|
|
--- a/src/main/java/org/spigotmc/AsyncCatcher.java
|
|
+++ b/src/main/java/org/spigotmc/AsyncCatcher.java
|
|
@@ -6,6 +6,7 @@ public class AsyncCatcher
|
|
{
|
|
|
|
public static boolean enabled = true;
|
|
+ public static boolean shuttingDown = false; // Paper
|
|
|
|
public static void catchOp(String reason)
|
|
{
|
|
diff --git a/src/main/java/org/spigotmc/RestartCommand.java b/src/main/java/org/spigotmc/RestartCommand.java
|
|
index 882e93ad4471e3688f2fcfb1e6f16926786ee5e7..94d8ba376cd1f024b244654cac9bb62bb19e3060 100644
|
|
--- a/src/main/java/org/spigotmc/RestartCommand.java
|
|
+++ b/src/main/java/org/spigotmc/RestartCommand.java
|
|
@@ -43,6 +43,7 @@ public class RestartCommand extends Command
|
|
private static void restart(final String restartScript)
|
|
{
|
|
AsyncCatcher.enabled = false; // Disable async catcher incase it interferes with us
|
|
+ org.spigotmc.AsyncCatcher.shuttingDown = true; // Paper
|
|
try
|
|
{
|
|
String[] split = restartScript.split( " " );
|