diff options
author | Shane Freeder <[email protected]> | 2024-04-11 16:42:18 +0100 |
---|---|---|
committer | Shane Freeder <[email protected]> | 2024-04-11 16:42:18 +0100 |
commit | d6a648d1f8e3b5a617306d3ee67d666752f4226a (patch) | |
tree | 3431fd58ed13bf49ba6df291f3e8e2a3b190f06b | |
parent | 5436d44bf2509ff89129f8790ee4643f09c72871 (diff) | |
download | Paper-fix/stackoverflow-on-stop.tar.gz Paper-fix/stackoverflow-on-stop.zip |
Fix StackOverflowException being thrown on server shutdownfix/stackoverflow-on-stop
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.
5 files changed, 80 insertions, 42 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 396697ea84..4c9fdb2bce 100644 --- a/patches/server/1013-Use-Velocity-compression-and-cipher-natives.patch +++ b/patches/server/1013-Use-Velocity-compression-and-cipher-natives.patch @@ -5,7 +5,7 @@ Subject: [PATCH] Use Velocity compression and cipher natives diff --git a/build.gradle.kts b/build.gradle.kts -index 5d35409137aff0eab242a0d4eb235e10cb7fe236..9c323b4ad76ee8a6386bca52d56615fd98e6d3cb 100644 +index f9056ee057a22a11288405cd42cd0ba4c9d120c3..bcfe59b6efb628ee1e7f9d60667360d4d885fb6a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -40,6 +40,11 @@ dependencies { @@ -264,10 +264,10 @@ index 859af8c845bae9781a62fa4acae56c6e2d449e10..f67f59f287d9a5cdd685b6b56ed1daf3 return this.threshold; } 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; } @@ -300,7 +300,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 e69bd162ef..1b08cfbfd4 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 @@ -122,7 +122,7 @@ index 9d18da228c6709e7665ba8babb6ee6d0b36b5dc5..af9f58328c09dddb2875f79128f906b8 private void tickPassenger(Entity vehicle, Entity passenger) { diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java -index f220e9ba35b07b690df93b1d733e9c666c772de9..c1a8de736ee39e4e177399bc51aedfd135a8100d 100644 +index 511d223c6278a8d516fa6f68b79d80ce1e8f9bff..fd77c587a0e546914f30f75dfd1ebe9ce36c2790 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -1063,8 +1063,43 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, S |