Summary
The implementation of SimpleTerminableRegistry.close() cause ConcurrentModificationException in multi threads context.
Steps to reproduce
This bug occurs randomly when casting some aura and can not be reproduced stablely. I have checked the source and found out the cause.
Here is the stacktrace:
java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1095)
at java.base/java.util.ArrayList$ListItr.previous(ArrayList.java:1122)
at com.google.common.collect.Lists$ReverseList$1.next(Lists.java:935)
at java.base/java.lang.Iterable.forEach(Iterable.java:74)
at MythicMobs-5.7.2.jar//io.lumine.mythic.bukkit.utils.terminable.SimpleTerminableRegistry.close(SimpleTerminableRegistry.java:31)
at MythicMobs-5.7.2.jar//io.lumine.mythic.bukkit.utils.terminable.Terminable.closeAndReportException(Terminable.java:61)
at MythicMobs-5.7.2.jar//io.lumine.mythic.bukkit.utils.terminable.Terminable.terminate(Terminable.java:18)
at MythicMobs-5.7.2.jar//io.lumine.mythic.core.skills.auras.Aura$AuraTracker.close(Aura.java:634)
at MythicMobs-5.7.2.jar//io.lumine.mythic.bukkit.utils.terminable.Terminable.closeAndReportException(Terminable.java:61)
at MythicMobs-5.7.2.jar//io.lumine.mythic.bukkit.utils.terminable.Terminable.terminate(Terminable.java:18)
at MythicMobs-5.7.2.jar//io.lumine.mythic.core.skills.auras.Aura$AuraTracker.run(Aura.java:568)
at MythicMobs-5.7.2.jar//io.lumine.mythic.bukkit.utils.Delegates$RunnableToConsumer.accept(Delegates.java:93)
at MythicMobs-5.7.2.jar//io.lumine.mythic.bukkit.utils.Schedulers$LumineTask.run(Schedulers.java:184)
at org.bukkit.craftbukkit.scheduler.CraftTask.run(CraftTask.java:86)
at org.bukkit.craftbukkit.scheduler.CraftAsyncTask.run(CraftAsyncTask.java:57)
at com.destroystokyo.paper.ServerSchedulerReportingWrapper.run(ServerSchedulerReportingWrapper.java:22)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)
at java.base/java.lang.Thread.run(Thread.java:1583)
The SimpleTerminableRegistry.close() method will iterate the termibales#List<Terminable> field in multi threads context. The list has been synchronized through Collections.synchronizedList() method. Howerver, the Collections#SynchronizedList.iterator()
method is not synced and needs to be synced manually but not in the code. The List.forEach() method will invoke the
unsynced List.iterator() method, causing ConcurrentModificationException.
[Legacy attachment omitted]
Proposed fixes
Sync the iteration in some way.
I have checked the source and this bug still exists in MM-5.8.0. But have not gotten it reproduced yet because of randomness.