adam9899 / Issues

14 stars 0 forks source link

Summoning Altars on the moon can cause server freezes #940

Open Maxwell-lt opened 3 years ago

Maxwell-lt commented 3 years ago

Many players have experienced persistent server freeze issues after exploring the moon, which can only be fixed with a rollback. My server has taken to calling it the Moon Curse.

Symptoms of the Moon Curse

Steps to reproduce

  1. Find a Summoning Altar on the moon
  2. Fly away until the chunk containing the Summoning Altar unloads

Step 2 may need to be repeated multiple times. In my testing I have been able to consistently trigger the Moon Curse in a single pass with one Summoning Altar, but another altar took several passes before it triggered the Moon Curse.

Potential mitigations

Existing reports about the same issue:

Technical explanation of the Moon Curse

This is an overview of the information I've been able to derive from attaching a remote debugger to the server process, I'm still unsure on what the root causes are.

Normally, the NBT of the Summoning Altar looks something like this:

{
    ForgeData: {},
    configTag: {
        pos: {
            X: -9602,
            Y: 97,
            Z: 2379
        }
    },
    x: -9602,
    y: 97,
    ForgeCaps: {
        "nuclearcraft:capability_default_radiation_resistance": {
            radiationResistance: 0d
        }
    },
    z: 2379,
    id: "from_the_depths:block_altar_of_summoning"
}

When the game attempts to write chunk data to the disk, it has to convert the data in memory to a string. This is done with indirect recursion through the write() (func_74734_a) and writeEntry() (func_150298_a) methods in NBTTagCompound.

I can't explain why, but occasionally the ForgeData tag of the Summoning Altar contains itself. This causes the indirect recursion to continue indefinitely, writing out an NBT tag that looks like this:

{
    ForgeData: {
        ForgeData: {
            ForgeData: {
                ForgeData: {
                    ForgeData: {
                        ForgeData: {
...continued

After the stackframe limit is reached (about 17k frames on my machine), the File IO Thread will crash with a StackOverflowError. As far as I can tell, the region file isn't actually written, so looking through the region file with an NBT viewer will show nothing amiss.

After the Moon Curse is triggered, players will occasionally cause the server to freeze by joining, even if no one is on the moon. The main server thread sleeps in a loop until an IO operation completes. I assume that this IO operation is stalling for the same reason as the stackoverflow.