InnovativeOnlineIndustries / Titanium

Other
8 stars 25 forks source link

Fix occasional CME during mod startup #114

Closed Quinteger closed 2 years ago

Quinteger commented 2 years ago

Occasionally, you can encounter a crash during mod initialization which looks something like this:

-- Head --
Thread: Render thread
Stacktrace:
    at java.util.HashMap.computeIfAbsent(HashMap.java:1221) ~[?:?] {re:mixin}
-- MOD industrialforegoing --
Details:
    Caused by 0: java.lang.reflect.InvocationTargetException
        at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:?] {}
        at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77) ~[?:?] {}
        at jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:?] {}
        at java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) ~[?:?] {}
        at java.lang.reflect.Constructor.newInstance(Constructor.java:480) ~[?:?] {}
        at net.minecraftforge.fml.javafmlmod.FMLModContainer.constructMod(FMLModContainer.java:67) ~[javafmllanguage-1.18.2-40.1.69.jar%23325!/:?] {}
        at net.minecraftforge.fml.ModContainer.lambda$buildTransitionHandler$4(ModContainer.java:106) ~[fmlcore-1.18.2-40.1.69.jar%23324!/:?] {}
        at java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804) ~[?:?] {}
        at java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1796) ~[?:?] {}
        at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) ~[?:?] {}
        at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182) ~[?:?] {}
        at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655) ~[?:?] {re:computing_frames}
        at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622) ~[?:?] {re:computing_frames}
        at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165) ~[?:?] {}

    Mod File: /C:/Users/Quinteger/AppData/Roaming/gdlauncher_next/instances/DW20-1.18/mods/industrial-foregoing-1.18.2-3.3.1.4-8.jar
    Failure message: Industrial Foregoing (industrialforegoing) has failed to load correctly
        java.lang.reflect.InvocationTargetException: null
    Mod Version: 3.3.1.4
    Mod Issue URL: NOT PROVIDED
    Exception message: java.util.ConcurrentModificationException
Stacktrace:
    at java.util.HashMap.computeIfAbsent(HashMap.java:1221) ~[?:?] {re:mixin}
    at com.hrznstudio.titanium.reward.RewardManager.getGiver(RewardManager.java:32) ~[titanium-1.18.2-3.5.6-38.jar%23303!/:3.5.6] {re:classloading}
    at com.buuz135.industrial.IndustrialForegoing.<init>(IndustrialForegoing.java:121) ~[industrial-foregoing-1.18.2-3.3.1.4-8.jar%23174!/:3.3.1.4] {re:classloading}
    at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[?:?] {}
    at jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77) ~[?:?] {}
    at jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[?:?] {}
    at java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499) ~[?:?] {}
    at java.lang.reflect.Constructor.newInstance(Constructor.java:480) ~[?:?] {}
    at net.minecraftforge.fml.javafmlmod.FMLModContainer.constructMod(FMLModContainer.java:67) ~[javafmllanguage-1.18.2-40.1.69.jar%23325!/:?] {}
    at net.minecraftforge.fml.ModContainer.lambda$buildTransitionHandler$4(ModContainer.java:106) ~[fmlcore-1.18.2-40.1.69.jar%23324!/:?] {}
    at java.util.concurrent.CompletableFuture$AsyncRun.run(CompletableFuture.java:1804) ~[?:?] {}
    at java.util.concurrent.CompletableFuture$AsyncRun.exec(CompletableFuture.java:1796) ~[?:?] {}
    at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) ~[?:?] {}
    at java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182) ~[?:?] {}
    at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655) ~[?:?] {re:computing_frames}
    at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622) ~[?:?] {re:computing_frames}
    at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165) ~[?:?] {}

RewardManager is not thread-safe and mod loading happens in parallel, which can result in the above behavior, if you're (un)lucky. Solution: swap HashMap for a ConcurrentHashMap. This PR is against 1.19, but should be easy enough to backport to 1.18 if neccessary.

CLAassistant commented 2 years ago

CLA assistant check
All committers have signed the CLA.