mojira.dev
MC-122976

Server Watchdog shuts down the server due to 60s tick despite server being responsive albeit slow

It manifests itself when the game slows down significantly below 20tps, yet still chuggs along at low, but considerable TPS. Then server may crash with the following message:

10:51:13 PM [INFO] game: I am alive and ticking
10:51:15 PM [INFO] game: I am just slow
10:51:15 PM [INFO] game: I am fine, don't worry
10:51:16 PM [Server Watchdog/FATAL]: A single server tick took 60.00 seconds (should be max 0.05)
10:51:16 PM [Server Watchdog/FATAL]: Considering it to be crashed, server will forcibly shutdown.
10:51:16 PM [Server Watchdog/ERROR]: This crash report has been saved to: C:\Users\gnembon\Desktop\servers\Test1.\crash-reports\crash-2017-12-06_22.51.16-server.txt
10:51:16 PM [INFO] Stopping server
10:51:16 PM [INFO] Saving players
[GUI] The server has stopped...

The server falls behind, but not 60s per tick.

The reason of this is because the watchdog server takes the difference between the last time server set .currentTime and .getCurrentTimeMillis as an indication of the last time server was done with the tick as per

in ServerHangWatchdog

long i = this.server.getCurrentTime();
            long j = MinecraftServer.getCurrentTimeMillis();
            long k = j - i;

            if (k > this.maxTickTime)
            {
                #CRASH

which is not correct as if the server has a tick buildup (falling behind), and presumably these ticks are not executed faster then the previous ones, it doesn't update server .currentTime in between these catchup ticks.

in MinecraftServer.java

i += j;
                    this.currentTime = k;

                    if (this.worldServers[0].areAllPlayersAsleep())
                    {
                        this.tick();
                        i = 0L;
                    }
                    else
                    {
                        while (i > 50L)
                        {
                            i -= 50L;
                            this.tick();
                        }
                    }

Solution Suggestion:
I assume that the max-tick-time in server.properties is reflecting a duration of a SINGLE tick, then the following addition should ensure this is true, so the watchdog could reliably read the length of the previous tick:

in MinecraftServer.java

i += j;
                    this.currentTime = k;

                    if (this.worldServers[0].areAllPlayersAsleep())
                    {
                        this.tick();
                        i = 0L;
                    }
                    else
                    {
                        while (i > 50L)
                        {
                            i -= 50L;
                            this.tick();
                            this.currentTime = getCurrentTimeMillis();   // for sure this one
                            this.serverIsRunning = True;                        // possibly also this one, although this variable is not used anywhere else, its just set to True.
                        }
                    }

Linked issues

Comments 5

Please do not mark unreleased versions as affected.
You don't have access to them yet.

I did verify it code-wise with 1.12. For obvious reasons didn't verify it under 1.13

Is this still an issue in release 1.13?

its already resolved in 1.13. I just didn't have a chance to give it a proper test to verify, that it is the case, but it is already changed in code.

Ah, yeah, it's a duplicate of MC-121586 which was already fixed (it's been on my to-do list to reconcile the info between the two for a long time, but now that the other one's already marked as fixed I guess we can just mark this as duplicate).

gnembon

(Unassigned)

Confirmed

Minecraft 1.12.2, Minecraft 17w49b, Minecraft 1.13-pre4

Retrieved