Pig with really large Motion values causes enough lag on chunk load to crash server (watchdog timeout)

XMLWordPrintable

    • Type: Bug
    • Resolution: Fixed
    • Priority: Minor
    • None
    • Affects Version/s: None
    • None
    • Environment:

      Somehow, my world ended up with a Pig that had an absurd velocity saved in the world file. I have no idea how this happened.

      The values from the NBT tag Motion for this entity are:

      -113717.336441621
      -0.0784000015258789
      88704.3049971832

      When I load this world in vanilla Minecraft, and log in with a player who's near the pig (so the chunk gets loaded), there's no issue. When I load it in CraftBukkit, the server lags for an abnormally long time, and eventually the watchdog thread kills it since it takes more than 60 seconds to process the tick. If I bump the timeout up to 6000 seconds, it will eventually finish processing the tick, and then the server appears to behave normally from that point forward.

      The stack of these crashes is always the following:

      java.lang.Error
      	at app//org.bukkit.craftbukkit.libs.it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap.containsKey(Long2ObjectOpenHashMap.java:469)
      	at app//net.minecraft.server.v1_12_R1.ChunkProviderServer.isLoaded(ChunkProviderServer.java:333)
      	at app//net.minecraft.server.v1_12_R1.WorldServer.isChunkLoaded(WorldServer.java:421)
      	at app//net.minecraft.server.v1_12_R1.World.a(World.java:239)
      	at app//net.minecraft.server.v1_12_R1.World.isLoaded(World.java:235)
      	at app//net.minecraft.server.v1_12_R1.World.a(World.java:1114)
      	at app//net.minecraft.server.v1_12_R1.World.getCubes(World.java:1157)
      	at app//net.minecraft.server.v1_12_R1.Entity.move(Entity.java:642)
      	at app//net.minecraft.server.v1_12_R1.EntityLiving.a(EntityLiving.java:1801)
      	at app//net.minecraft.server.v1_12_R1.EntityPig.a(EntityPig.java:226)
      	at app//net.minecraft.server.v1_12_R1.EntityLiving.n(EntityLiving.java:2105)
      	at app//net.minecraft.server.v1_12_R1.EntityInsentient.n(EntityInsentient.java:507)
      	at app//net.minecraft.server.v1_12_R1.EntityAgeable.n(EntityAgeable.java:133)
      	at app//net.minecraft.server.v1_12_R1.EntityAnimal.n(EntityAnimal.java:27)
      	at app//net.minecraft.server.v1_12_R1.EntityLiving.B_(EntityLiving.java:1932)
      	at app//net.minecraft.server.v1_12_R1.EntityInsentient.B_(EntityInsentient.java:246)
      	at app//net.minecraft.server.v1_12_R1.World.entityJoinedWorld(World.java:1507)
      	at app//net.minecraft.server.v1_12_R1.World.h(World.java:1482)
      	at app//net.minecraft.server.v1_12_R1.World.tickEntities(World.java:1344)
      	at app//net.minecraft.server.v1_12_R1.WorldServer.tickEntities(WorldServer.java:646)
      	at app//net.minecraft.server.v1_12_R1.MinecraftServer.D(MinecraftServer.java:750)
      	at app//net.minecraft.server.v1_12_R1.DedicatedServer.D(DedicatedServer.java:371)
      	at app//net.minecraft.server.v1_12_R1.MinecraftServer.C(MinecraftServer.java:651)
      	at app//net.minecraft.server.v1_12_R1.MinecraftServer.run(MinecraftServer.java:555)
      	at java.base@9/java.lang.Thread.run(Thread.java:844)
      

      I ran with a profiler attached, and found that because of the abnormally high values for Motion, the bounding box that gets passed into app//net.minecraft.server.v1_12_R1.Entity.move(Entity.java:642) is:

      box[-112031.852090029, 60.92159999847412, 8255.479289371024 -> 1686.384351568523, 61.89999997615814, 96960.68428653038] 

      or, effectively a 113718 x 88705 meter area (7107 x 5544 chunk area), or 39,401,208 total chunks that it tries to check whether they're loaded or not. Obviously this is way more than Minecraft was anticipating, so it takes abnormally long to process this before going back to normal.

      This change (in Entity.patch) appears to remove the safety check for anything that is a Vehicle, which means it also applies to Pigs (since they're rideable):

      +            // CraftBukkit start - Exempt Vehicles from notch's sanity check
      +            if (!(getBukkitEntity() instanceof Vehicle)) {
      +                if (Math.abs(this.motX) > 10.0D) {
      +                    this.motX = 0.0D;
      +                }
      +
      +                if (Math.abs(this.motY) > 10.0D) {
      +                    this.motY = 0.0D;
      +                }
      +
      +                if (Math.abs(this.motZ) > 10.0D) {
      +                    this.motZ = 0.0D;
      +                }
      +            }
      +            // CraftBukkit end
      

       The original logic in vanilla Minecraft does apply this check to every entity, so it's not a problem when loading this world in that server. I think there should be some sanity check for vehicles in CraftBukkit as well - maybe configurable limits, maybe using the entity's expected speed (e.g. some multiple of the MOVEMENT_SPEED attribute).

            Assignee:
            Unassigned
            Reporter:
            Raivo Lindemann
            Votes:
            1 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: