
Fatal server stall - MobGrindUtils & EnderIO interaction
MxtressMyxx opened this issue · 11 comments
Issue Description:
Fatal server stall occurs as interaction between EnderIO Repellent enchantment and MobGrindingUtils MobMasher.
As described by one of our members:
This seems to be an interaction between the mob grinder from mob_grinding_utils and an enchantment in EnderIO (EnchantmentRepellent). My best guess is that a mob spawned with a piece of equipment bearing this enchantment, which tried to teleport the mob grinder's fakeplayer away when it attacked the mob. Given that the fakeplayer in question never moves and attacks very rapidly in quick succession, I'm guessing it got stuck endlessly trying to teleport the fakeplayer.
What happens:
Server fatally stalls when a mob bearing a piece of gear with the Repellant enchanment is attacked by the MobGrindUtils fakePlayer, causing an attempt to teleport the fakePlayer
What you expected to happen:
n/a
Steps to reproduce:
- Spawn mob with gear that had Repellent enhancement
- Attempt to kill mob using MobGrundUtils MobMasher
- Fatal stall
Affected Versions (Do not use "latest"):
- EnderIO: Ender IO - 5.0.29
- EnderCore: EnderCore - 1.12.2-0.5.35
- Minecraft: 1.12.2
- Forge: 2727
Your most recent log file where the issue was present:
https://gist.github.com/AnsuzThurisaz/a18d72919dedcc19debb5cb0ed2686dd
From @HenryLoenwind
"Do you have a couple more stall reports to confirm the exact location? As it's just a snapshot of what's going on at the time the stall reporting decides there maybe a stall, it may be a good bit off.
Anyway, I'll add a fakeplayer detection for (all kinds of) teleporting just to be safe."
After some digging I'd like to say that I think this has nothing to do with FakePlayers and the FakePlayer in this case is simply doing something to result in a guaranteed method through which to trigger this fatal freeze. What I believe causes this is a poorly designed while loop:
Negative numbers that are too large increase the amount of time that it would take to meet the condition drastically. If the enchantment is level 1 a y value of simply -47 would cause the condition to fail over 99% of the time (just explaining normal distribution for posterity's sake).
In this scenario Mob Grinding Util's Mob Masher (or Saw, internally) places the entity at -100D as per:
That'd be 6.3125 standard deviations from the mean (assuming level 1 enchant). This results in roughly a 1 in 20 billion chance of being greater than 1.1, and it runs 15 times. I'm not sure how FakePlayers work, especially since it should be teleporting to that Y value every strike, but is there a possibility it could be returning an even lower Y value? I'd imagine entities even lower than -100 would be even worse.
You could likely recreate this with any entity that low, though I'm not sure what things can make you immune to void damage to recreate this, and -64 with the level 1 enchant simply didn't work to recreate the fatal freeze.
All in all it's a fairly specific edge case, but I think it'd help to fix the loop in addition to the fakeplayer check. Maybe make it not work at all below a certain Y value, like -65?
Ideally it probably shouldn't loop at all, as it's a random number with a theoretical infinite amount of values that can keep it below 1.1. Maybe make numbers below 1.1 round up to 2?
EDIT: My 1 in 20 billion chance was calculated incorrectly and it's actually several magnitudes worse than that. I mean like, 7σ is nearly 1 trillion, and it's actually 12.6σ so 4.73609... × 10^35. That's a big number.
This bug just took down forgecraft 2. It looks like any low y-level combat could trigger this problem.
For those critically affected by this bug, you can try this dev build at your own risk: https://ci.tterrag.com/job/EnderIO-Modules/job/EnderIO-Hourly/581/
(If it's a 404, come back later. Commenting now before I forget :P)
(I have not tested the dev build, but)
That commit should fix fatal freezes technically. It's worth noting that there's a 50% chance for the while loop to fail every iteration at or below a mean of 1. While statistically unlikely, it means lag spikes can still occur (especially since in the event of an impossible teleport it repeats the process up to 14 more times) depending on RNG. And while this should never occur naturally, calling that method with a range of 0 will fatally freeze still.
EDIT: Oh, and if anyone is using cubic chunks and they're below 0 I hope they enjoy getting teleported up up to y=2, because that's what will happen if I'm not mistaken. Even if they're at y=-200.