Paper/patches/server/0818-Fix-premature-player-kicks-on-shutdown.patch
Shane Freeder 46d462b83e
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.
2024-04-12 12:37:00 -07:00

62 lines
3.3 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shane Freeder <theboyetronic@gmail.com>
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);
}