aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorShane Freeder <[email protected]>2024-04-12 20:37:00 +0100
committerGitHub <[email protected]>2024-04-12 12:37:00 -0700
commit46d462b83e74d07735af05ee352844d02906b4a7 (patch)
treec6f7b8fd91c3ff600b2e1654ad2203ab4074913b
parent8fe90dede7364a3c4aec17c4ef191b946f43d96e (diff)
downloadPaper-46d462b83e74d07735af05ee352844d02906b4a7.tar.gz
Paper-46d462b83e74d07735af05ee352844d02906b4a7.zip
Fix StackOverflowException thrown on shutdown (Fixes #10404) (#10408)
paper previously migrated away from using executeIfPossible as this throws a RejectedExecutionException when the server is shutting down, which is then picked up by the Connection handler object and causes the player to be kicked without the intended disconnection message that comes from commands such as /stop, /restart This was fine, because previously changes made in spigot would just prevent these packets from being executed anyways. Instead, we'll just use a marker exception to try to detect this specific state.
-rw-r--r--patches/server/0818-Fix-player-kick-on-shutdown.patch23
-rw-r--r--patches/server/0818-Fix-premature-player-kicks-on-shutdown.patch61
-rw-r--r--patches/server/0985-Optimize-Network-Manager-and-add-advanced-packet-sup.patch20
-rw-r--r--patches/server/1013-Use-Velocity-compression-and-cipher-natives.patch6
-rw-r--r--patches/server/1014-Detail-more-information-in-watchdog-dumps.patch8
5 files changed, 78 insertions, 40 deletions
diff --git a/patches/server/0818-Fix-player-kick-on-shutdown.patch b/patches/server/0818-Fix-player-kick-on-shutdown.patch
deleted file mode 100644
index 6b694a6abe..0000000000
--- a/patches/server/0818-Fix-player-kick-on-shutdown.patch
+++ /dev/null
@@ -1,23 +0,0 @@
-From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
-From: Denery <[email protected]>
-Date: Sun, 6 Nov 2022 02:02:46 +0300
-Subject: [PATCH] Fix player kick on shutdown
-
-Fix preemptive player kick on a server shutdown.
-If you update minecraft version / upstream and something is changed in this method make sure that a server doesn't disconnect a player preemptively,
-also check if all packets are ignored during the shutdown process.
-See net.minecraft.network.Connection#channelRead0(ChannelHandlerContext, Packet) and net.minecraft.util.thread.BlockableEventLoop#executeIfPossible(Runnable)
-
-diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
-index b7ffab0284b0bccd79775b8d03c8b2e088f91d1d..4202c48ad8f8e85ef46d1bd446ab28f3f4b083d1 100644
---- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java
-+++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
-@@ -26,7 +26,7 @@ public class PacketUtils {
-
- public static <T extends PacketListener> void ensureRunningOnSameThread(Packet<T> packet, T listener, BlockableEventLoop<?> engine) throws RunningOnDifferentThreadException {
- if (!engine.isSameThread()) {
-- engine.executeIfPossible(() -> {
-+ engine.execute(() -> { // Paper - Fix preemptive player kick on a server shutdown
- if (listener instanceof ServerCommonPacketListenerImpl serverCommonPacketListener && serverCommonPacketListener.processedDisconnect) return; // CraftBukkit - Don't handle sync packets for kicked players
- if (listener.shouldHandleMessage(packet)) {
- co.aikar.timings.Timing timing = co.aikar.timings.MinecraftTimings.getPacketTiming(packet); // Paper - timings
diff --git a/patches/server/0818-Fix-premature-player-kicks-on-shutdown.patch b/patches/server/0818-Fix-premature-player-kicks-on-shutdown.patch
new file mode 100644
index 0000000000..983dbfd32a
--- /dev/null
+++ b/patches/server/0818-Fix-premature-player-kicks-on-shutdown.patch
@@ -0,0 +1,61 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Shane Freeder <[email protected]>
+Date: Thu, 11 Apr 2024 16:37:44 +0100
+Subject: [PATCH] Fix premature player kicks on shutdown
+
+When the server is stopping, the default execution handler method will throw a
+RejectedExecutionException in order to prevent further execution, this causes
+us to lose the actual kick reason. To mitigate this, we'll use a seperate marked
+class in order to gracefully ignore these.
+
+diff --git a/src/main/java/io/papermc/paper/util/ServerStopRejectedExecutionException.java b/src/main/java/io/papermc/paper/util/ServerStopRejectedExecutionException.java
+new file mode 100644
+index 0000000000000000000000000000000000000000..2c5cd77103c5a33d4349ab6b9ee2d8378bb60eb4
+--- /dev/null
++++ b/src/main/java/io/papermc/paper/util/ServerStopRejectedExecutionException.java
+@@ -0,0 +1,20 @@
++package io.papermc.paper.util;
++
++import java.util.concurrent.RejectedExecutionException;
++
++public class ServerStopRejectedExecutionException extends RejectedExecutionException {
++ public ServerStopRejectedExecutionException() {
++ }
++
++ public ServerStopRejectedExecutionException(final String message) {
++ super(message);
++ }
++
++ public ServerStopRejectedExecutionException(final String message, final Throwable cause) {
++ super(message, cause);
++ }
++
++ public ServerStopRejectedExecutionException(final Throwable cause) {
++ super(cause);
++ }
++}
+diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
+index 22a7f17180b76b6c3548d3b54ae8218a469401a8..c399625a342ffd61102bb96a97ac24b0669e8e17 100644
+--- a/src/main/java/net/minecraft/network/Connection.java
++++ b/src/main/java/net/minecraft/network/Connection.java
+@@ -290,6 +290,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+ Connection.genericsFtw(packet, packetlistener);
+ } catch (RunningOnDifferentThreadException cancelledpackethandleexception) {
+ ;
++ } catch (io.papermc.paper.util.ServerStopRejectedExecutionException ignored) { // Paper - do not prematurely disconnect players on stop
+ } catch (RejectedExecutionException rejectedexecutionexception) {
+ this.disconnect(Component.translatable("multiplayer.disconnect.server_shutdown"));
+ } catch (ClassCastException classcastexception) {
+diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
+index bfee202e1dc8ea875b9d2b4e8c3b0be3f6d94b26..d50d3bc9c0f573cdb43100bce6e3dbfe2102fc53 100644
+--- a/src/main/java/net/minecraft/server/MinecraftServer.java
++++ b/src/main/java/net/minecraft/server/MinecraftServer.java
+@@ -2013,7 +2013,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
+ @Override
+ public void executeIfPossible(Runnable runnable) {
+ if (this.isStopped()) {
+- throw new RejectedExecutionException("Server already shutting down");
++ throw new io.papermc.paper.util.ServerStopRejectedExecutionException("Server already shutting down"); // Paper - do not prematurely disconnect players on stop
+ } else {
+ super.executeIfPossible(runnable);
+ }
diff --git a/patches/server/0985-Optimize-Network-Manager-and-add-advanced-packet-sup.patch b/patches/server/0985-Optimize-Network-Manager-and-add-advanced-packet-sup.patch
index 6ab7cbf215..2e8076eb2e 100644
--- a/patches/server/0985-Optimize-Network-Manager-and-add-advanced-packet-sup.patch
+++ b/patches/server/0985-Optimize-Network-Manager-and-add-advanced-packet-sup.patch
@@ -28,7 +28,7 @@ and then catch exceptions and close if they fire.
Part of this commit was authored by: Spottedleaf, sandtechnology
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
-index 22a7f17180b76b6c3548d3b54ae8218a469401a8..7f2aa5e17fe675f3404d67b1794d2ca68b188eb9 100644
+index c399625a342ffd61102bb96a97ac24b0669e8e17..16eb94eb1f40485daef2713f740f6e0beeb1463f 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
@@ -84,7 +84,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
@@ -51,7 +51,7 @@ index 22a7f17180b76b6c3548d3b54ae8218a469401a8..7f2aa5e17fe675f3404d67b1794d2ca6
// Paper start - add utility methods
public final net.minecraft.server.level.ServerPlayer getPlayer() {
-@@ -375,15 +379,39 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+@@ -376,15 +380,39 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
}
public void send(Packet<?> packet, @Nullable PacketSendListener callbacks, boolean flush) {
@@ -97,7 +97,7 @@ index 22a7f17180b76b6c3548d3b54ae8218a469401a8..7f2aa5e17fe675f3404d67b1794d2ca6
}
public void runOnceConnected(Consumer<Connection> task) {
-@@ -391,7 +419,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+@@ -392,7 +420,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
this.flushQueue();
task.accept(this);
} else {
@@ -106,7 +106,7 @@ index 22a7f17180b76b6c3548d3b54ae8218a469401a8..7f2aa5e17fe675f3404d67b1794d2ca6
}
}
-@@ -409,6 +437,14 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+@@ -410,6 +438,14 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
}
private void doSendPacket(Packet<?> packet, @Nullable PacketSendListener callbacks, boolean flush) {
@@ -121,7 +121,7 @@ index 22a7f17180b76b6c3548d3b54ae8218a469401a8..7f2aa5e17fe675f3404d67b1794d2ca6
ChannelFuture channelfuture = flush ? this.channel.writeAndFlush(packet) : this.channel.write(packet);
if (callbacks != null) {
-@@ -428,14 +464,24 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+@@ -429,14 +465,24 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
});
}
@@ -147,7 +147,7 @@ index 22a7f17180b76b6c3548d3b54ae8218a469401a8..7f2aa5e17fe675f3404d67b1794d2ca6
}
}
-@@ -468,20 +514,57 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+@@ -469,20 +515,57 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
return attributekey;
}
@@ -212,7 +212,7 @@ index 22a7f17180b76b6c3548d3b54ae8218a469401a8..7f2aa5e17fe675f3404d67b1794d2ca6
private static final int MAX_PER_TICK = io.papermc.paper.configuration.GlobalConfiguration.get().misc.maxJoinsPerTick; // Paper - Buffer joins to world
private static int joinAttemptsThisTick; // Paper - Buffer joins to world
-@@ -544,6 +627,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+@@ -545,6 +628,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
public void disconnect(Component disconnectReason) {
// Spigot Start
this.preparing = false;
@@ -220,7 +220,7 @@ index 22a7f17180b76b6c3548d3b54ae8218a469401a8..7f2aa5e17fe675f3404d67b1794d2ca6
// Spigot End
if (this.channel == null) {
this.delayedDisconnect = disconnectReason;
-@@ -715,7 +799,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+@@ -716,7 +800,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
public void handleDisconnection() {
if (this.channel != null && !this.channel.isOpen()) {
if (this.disconnectionHandled) {
@@ -229,7 +229,7 @@ index 22a7f17180b76b6c3548d3b54ae8218a469401a8..7f2aa5e17fe675f3404d67b1794d2ca6
} else {
this.disconnectionHandled = true;
PacketListener packetlistener = this.getPacketListener();
-@@ -728,7 +812,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+@@ -729,7 +813,7 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
packetlistener1.onDisconnect(ichatbasecomponent);
}
@@ -238,7 +238,7 @@ index 22a7f17180b76b6c3548d3b54ae8218a469401a8..7f2aa5e17fe675f3404d67b1794d2ca6
// Paper start - Add PlayerConnectionCloseEvent
final PacketListener packetListener = this.getPacketListener();
if (packetListener instanceof net.minecraft.server.network.ServerCommonPacketListenerImpl commonPacketListener) {
-@@ -765,4 +849,93 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+@@ -766,4 +850,93 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
public void setBandwidthLogger(SampleLogger log) {
this.bandwidthDebugMonitor = new BandwidthDebugMonitor(log);
}
diff --git a/patches/server/1013-Use-Velocity-compression-and-cipher-natives.patch b/patches/server/1013-Use-Velocity-compression-and-cipher-natives.patch
index a9cc979072..8ba0372a99 100644
--- a/patches/server/1013-Use-Velocity-compression-and-cipher-natives.patch
+++ b/patches/server/1013-Use-Velocity-compression-and-cipher-natives.patch
@@ -260,10 +260,10 @@ index 11a466558c77b43969b8e4be3a3470f84c7fcb1a..ae6e8ab9c1afa31d808f1fce2654a8b9
}
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
-index 7f2aa5e17fe675f3404d67b1794d2ca68b188eb9..fff375fd50fa1a804636a92ded1ae55cff42977d 100644
+index 16eb94eb1f40485daef2713f740f6e0beeb1463f..fae2a57570a4007b67b9949b9b16504da36a9886 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
-@@ -734,11 +734,28 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+@@ -735,11 +735,28 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
return networkmanager;
}
@@ -296,7 +296,7 @@ index 7f2aa5e17fe675f3404d67b1794d2ca68b188eb9..fff375fd50fa1a804636a92ded1ae55c
public boolean isEncrypted() {
return this.encrypted;
-@@ -771,16 +788,17 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+@@ -772,16 +789,17 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
public void setupCompression(int compressionThreshold, boolean rejectsBadPackets) {
if (compressionThreshold >= 0) {
diff --git a/patches/server/1014-Detail-more-information-in-watchdog-dumps.patch b/patches/server/1014-Detail-more-information-in-watchdog-dumps.patch
index 2dce8a04c2..e403a57375 100644
--- a/patches/server/1014-Detail-more-information-in-watchdog-dumps.patch
+++ b/patches/server/1014-Detail-more-information-in-watchdog-dumps.patch
@@ -7,10 +7,10 @@ Subject: [PATCH] Detail more information in watchdog dumps
- Dump player name, player uuid, position, and world for packet handling
diff --git a/src/main/java/net/minecraft/network/Connection.java b/src/main/java/net/minecraft/network/Connection.java
-index fff375fd50fa1a804636a92ded1ae55cff42977d..4716f8bd8a64d4f20f0d5957c1e7fabf63020f43 100644
+index fae2a57570a4007b67b9949b9b16504da36a9886..a536ebcf29d8ef0ed32863bd8d5e70f7a0636e8d 100644
--- a/src/main/java/net/minecraft/network/Connection.java
+++ b/src/main/java/net/minecraft/network/Connection.java
-@@ -586,7 +586,13 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
+@@ -587,7 +587,13 @@ public class Connection extends SimpleChannelInboundHandler<Packet<?>> {
if (!(this.packetListener instanceof net.minecraft.server.network.ServerLoginPacketListenerImpl loginPacketListener)
|| loginPacketListener.state != net.minecraft.server.network.ServerLoginPacketListenerImpl.State.VERIFYING
|| Connection.joinAttemptsThisTick++ < MAX_PER_TICK) {
@@ -25,7 +25,7 @@ index fff375fd50fa1a804636a92ded1ae55cff42977d..4716f8bd8a64d4f20f0d5957c1e7fabf
// Paper end - Buffer joins to world
}
diff --git a/src/main/java/net/minecraft/network/protocol/PacketUtils.java b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
-index 4202c48ad8f8e85ef46d1bd446ab28f3f4b083d1..32838f87978c0694bdb573236b7cdf72b2e363cd 100644
+index b7ffab0284b0bccd79775b8d03c8b2e088f91d1d..83302c252f54481f239522e5c6861ccfe233070a 100644
--- a/src/main/java/net/minecraft/network/protocol/PacketUtils.java
+++ b/src/main/java/net/minecraft/network/protocol/PacketUtils.java
@@ -18,6 +18,24 @@ public class PacketUtils {
@@ -56,7 +56,7 @@ index 4202c48ad8f8e85ef46d1bd446ab28f3f4b083d1..32838f87978c0694bdb573236b7cdf72
@@ -27,6 +45,8 @@ public class PacketUtils {
public static <T extends PacketListener> void ensureRunningOnSameThread(Packet<T> packet, T listener, BlockableEventLoop<?> engine) throws RunningOnDifferentThreadException {
if (!engine.isSameThread()) {
- engine.execute(() -> { // Paper - Fix preemptive player kick on a server shutdown
+ engine.executeIfPossible(() -> {
+ packetProcessing.push(listener); // Paper - detailed watchdog information
+ try { // Paper - detailed watchdog information
if (listener instanceof ServerCommonPacketListenerImpl serverCommonPacketListener && serverCommonPacketListener.processedDisconnect) return; // CraftBukkit - Don't handle sync packets for kicked players