CraftPlayer.onEntityRemove is not thread safe, crashing server
Nobody has claimed this yet.
- Dominant language
- Shell
- Stars
- 4.4k
- Forks
- 623
- PR merge metrics
- No merged PRs in 30d
Description
Stack trace
Region #~ centered at chunk [~, ~] in world 'world_nether' failed to tick:
net.minecraft.ReportedException: Exception ticking world
at net.minecraft.server.MinecraftServer.tickChildren(MinecraftServer.java:1878) ~[server-1.21.8.jar]
at net.minecraft.server.MinecraftServer.tickServer(MinecraftServer.java:1693) ~[server-1.21.8.jar]
at io.papermc.paper.threadedregions.TickRegions$ConcreteRegionTickHandle.tickRegion(TickRegions.java:409) ~[server-1.21.8.jar]
at io.papermc.paper.threadedregions.TickRegionScheduler$RegionScheduleHandle.runTick(TickRegionScheduler.java:437) ~[server-1.21.8.jar]
at ca.spottedleaf.concurrentutil.scheduler.SchedulerThreadPool$TickThreadRunner.run(SchedulerThreadPool.java:546) ~[concurrentutil-0.0.3.jar:?]
at java.base/java.lang.Thread.run(Thread.java:1474) ~[?:?]
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 2049
at it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap.rehash(Object2ObjectOpenHashMap.java:1281) ~[fastutil-8.5.15.jar:?]
at it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap.removeEntry(Object2ObjectOpenHashMap.java:209) ~[fastutil-8.5.15.jar:?]
at it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap.remove(Object2ObjectOpenHashMap.java:308) ~[fastutil-8.5.15.jar:?]
at org.bukkit.craftbukkit.entity.CraftPlayer.onEntityRemove(CraftPlayer.java:2212) ~[server-1.21.8.jar]
at net.minecraft.server.level.ServerLevel$EntityCallbacks.onTrackingEnd(ServerLevel.java:2989) ~[server-1.21.8.jar]
at net.minecraft.server.level.ServerLevel$EntityCallbacks.onTrackingEnd(ServerLevel.java:2834) ~[server-1.21.8.jar]
at ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup.entityStatusChange(EntityLookup.java:304) ~[server-1.21.8.jar]
at ca.spottedleaf.moonrise.patches.chunk_system.level.entity.ChunkEntitySlices.updateStatus(ChunkEntitySlices.java:255) ~[server-1.21.8.jar]
at ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup.chunkStatusChange(EntityLookup.java:334) ~[server-1.21.8.jar]
at ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder.changeEntityChunkStatus(NewChunkHolder.java:1212) ~[server-1.21.8.jar]
at ca.spottedleaf.moonrise.patches.chunk_system.scheduling.NewChunkHolder.handleFullStatusChange(NewChunkHolder.java:1310) ~[server-1.21.8.jar]
at ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.processPendingFullUpdate(ChunkHolderManager.java:1637) ~[server-1.21.8.jar]
at ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.processTicketUpdates(ChunkHolderManager.java:1606) ~[server-1.21.8.jar]
at ca.spottedleaf.moonrise.patches.chunk_system.scheduling.ChunkHolderManager.tick(ChunkHolderManager.java:1031) ~[server-1.21.8.jar]
at net.minecraft.world.level.TicketStorage.purgeStaleTickets(TicketStorage.java:254) ~[server-1.21.8.jar]
at net.minecraft.server.level.ServerChunkCache.tick(ServerChunkCache.java:499) ~[server-1.21.8.jar]
at net.minecraft.server.level.ServerLevel.tick(ServerLevel.java:791) ~[server-1.21.8.jar]
at net.minecraft.server.MinecraftServer.tickChildren(MinecraftServer.java:1873) ~[server-1.21.8.jar]
... 5 more
Plugin and Datapack List
plugins: ESU
Actions to reproduce (if known)
ESU is a plugin, which uses Player.hideEntity on player entity scheduler.
onEntityRemove and it may write to the map at the same time.
Folia version
ALL
Other
net.minecraft.server.level.ServerLevel$EntityCallbacks.onTrackingEnd(ServerLevel.java:2989)
// Folia - region threading - TODO THIS SHIT
if (!(entity instanceof ServerPlayer)) {
for (ServerPlayer player : ServerLevel.this.server.getPlayerList().players) { // Paper - call onEntityRemove for all online players
player.getBukkitEntity().onEntityRemove(entity);
}
}
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at CraftPlayer.onEntityRemove, where the stack trace shows the failure, and inspect ServerLevel$EntityCallbacks.onTrackingEnd and the shown player iteration. Reproduce with ESU using Player.hideEntity on the player entity scheduler, then verify that concurrent removal or map access no longer causes the reported crash.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend, distributed-systems
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100