Fabric API

Fabric API

106M Downloads

ConcurrentModificationException in net.fabricmc.fabric.impl.client.texture.SpriteRegistryCallbackHolder.eventLocal(Identifier)

aromanelli opened this issue · 5 comments

commented

Minecraft 1.14.2
fabric-loader-0.4.8+build.154-1.14.2+build.2
Fabric API 0.3.0+build.170 (though I've seen this problem with 'build.16#' versions too.)

Seeing an intermittent ConcurrentModificationException when Minecraft is starting up on the "MOJANG" progress bar window.

---- Minecraft Crash Report ----
// This doesn't make any sense!

Time: 5/28/19, 3:34 PM
Description: Rendering overlay

java.util.ConcurrentModificationException
	at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1134)
	at net.fabricmc.fabric.impl.client.texture.SpriteRegistryCallbackHolder.eventLocal(SpriteRegistryCallbackHolder.java:36)
	at net.minecraft.class_1059.localvar$beforeSpriteLoad$zbi000(class_1059.java:587)
	at net.minecraft.class_1059.method_18163(class_1059.java:117)
	at net.minecraft.class_702.method_18832(class_702.java:199)
	at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:642)
	at java.base/java.util.concurrent.CompletableFuture$Completion.exec(CompletableFuture.java:479)
	at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:290)
	at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1020)
	at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1656)
	at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1594)
	at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:177)


A detailed walkthrough of the error, its code path and all known details is as follows:
---------------------------------------------------------------------------------------

-- Head --
Thread: Client thread
Stacktrace:
	at java.base/java.util.HashMap.computeIfAbsent(HashMap.java:1134)

-- Overlay render details --
Details:
	Overlay name: net.minecraft.class_425
Stacktrace:
	at net.minecraft.class_757.method_3192(class_757.java:676)
	at net.minecraft.class_310.method_1523(class_310.java:954)
	at net.minecraft.class_310.method_1514(class_310.java:411)
	at net.minecraft.client.main.Main.main(Main.java:154)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:567)
	at net.fabricmc.loader.game.MinecraftGameProvider.launch(MinecraftGameProvider.java:170)
	at net.fabricmc.loader.launch.knot.Knot.init(Knot.java:129)
	at net.fabricmc.loader.launch.knot.KnotClient.main(KnotClient.java:26)

-- System Details --
Details:
	Minecraft Version: 1.14.2
	Operating System: Linux (amd64) version 5.1.5-050105-generic
	Java Version: 12.0.1, Private Build
	Java VM Version: OpenJDK 64-Bit Server VM (mixed mode, sharing), Private Build
	Memory: 1236544704 bytes (1179 MB) / 2113929216 bytes (2016 MB) up to 6442450944 bytes (6144 MB)
	JVM Flags: 8 total; -Xss1M -Xmx6G -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M
	Fabric Mods: 
		autoconfig1: Auto Config v1 1.0.1+mc1.14
		cleardespawn: Clear Despawn 1.0.4
		cloth-config: Cloth Config 0.2.1+build.14
		fabric: Fabric API 0.3.0+build.170
		fabric-api-base: fabric-api-base 0.1.0+59147463
		fabric-commands-v0: fabric-commands-v0 0.1.1+25fd0c52
		fabric-containers-v0: fabric-containers-v0 0.1.2+25fd0c52
		fabric-content-registries-v0: fabric-content-registries-v0 0.1.1+45e1a1c8
		fabric-crash-report-info-v1: fabric-crash-report-info-v1 0.1.0+59147463
		fabric-events-interaction-v0: fabric-events-interaction-v0 0.1.0+59147463
		fabric-events-lifecycle-v0: fabric-events-lifecycle-v0 0.1.0+59147463
		fabric-item-groups-v0: fabric-item-groups-v0 0.1.0+59147463
		fabric-keybindings-v0: fabric-keybindings-v0 0.1.0+59147463
		fabric-mining-levels-v0: fabric-mining-levels-v0 0.1.0+59147463
		fabric-models-v0: fabric-models-v0 0.1.0+59147463
		fabric-networking-blockentity-v0: fabric-networking-blockentity-v0 0.1.1+25fd0c52
		fabric-networking-v0: fabric-networking-v0 0.1.2+200eb5c2
		fabric-object-builders-v0: fabric-object-builders-v0 0.1.1+9fe2f882
		fabric-registry-sync-v0: fabric-registry-sync-v0 0.1.2+25fd0c52
		fabric-renderer-api-v1: fabric-renderer-api-v1 0.1.0+02a46d5b
		fabric-renderer-indigo: fabric-renderer-indigo 0.1.2+4076d79a
		fabric-rendering-data-attachment-v1: fabric-rendering-data-attachment-v1 0.1.0+02a46d5b
		fabric-rendering-fluids-v1: fabric-rendering-fluids-v1 0.1.0+dc4c57c2
		fabric-rendering-v0: fabric-rendering-v0 0.1.0+59147463
		fabric-resource-loader-v0: fabric-resource-loader-v0 0.1.1+59147463
		fabric-tag-extensions-v0: fabric-tag-extensions-v0 0.1.0+59147463
		fabric-textures-v0: fabric-textures-v0 0.1.2+25fd0c52
		fabricloader: Fabric Loader 0.4.8+build.154
		simplezoom: Simple Zoom 1.0.0
		tbo: TheBiomeOverhaul 1.2.0
	Launched Version: fabric-loader-0.4.8+build.154-1.14.2+build.2
	LWJGL: 3.2.1 build 12
	OpenGL: Radeon RX 580 Series (POLARIS10, DRM 3.30.0, 5.1.5-050105-generic, LLVM 8.0.0) GL version 4.5 (Compatibility Profile) Mesa 19.0.2, X.Org
	GL Caps: Using GL 1.3 multitexturing.
Using GL 1.3 texture combiners.
Using framebuffer objects because OpenGL 3.0 is supported and separate blending is supported.
Shaders are available because OpenGL 2.1 is supported.
VBOs are available because OpenGL 1.5 is supported.

	Using VBOs: Yes
	Is Modded: Definitely; Client brand changed to 'fabric'
	Type: Client (map_client.txt)
	Resource Packs: 
	Current Language: English (US)
	CPU: 12x Intel(R) Core(TM) i7 CPU 980 @ 3.33GHz

Looking at the source code for the SpriteRegistryCallbackHolder class it seems that the public 'eventLocal(Identifier)' method is not multi-threaded safe (synchronized, locking, etc.), or that the 'eventMap' HashMap being used should be a ConcurrentHashMap (depending on your preference for how to make a class thread safe).

Let me know if you need any further information.

commented

For testing purposes I added the 'synchronized' keyword to the declaration for method SpriteRegistryCallbackHolder.eventLocal(Identifier) and the exception does not occur.

commented

I have the same problem maybe 10% of the time I run Minecraft. I use MutliMC.

commented

@e00E Multithreading issues are usually driven based on race conditions, which is why you'd see it only 10% of the time.

For me, as I used earlier versions of the Fabric API library the problem happened less and less, and in (I think) 158 not at all, while always in v170.

commented

@asiekierka Apologies for the backseat driving, but looking at the fix, correct me if I'm wrong, but I think the way its coded now you can have two puts into the Map (race condition on line 46 the null check, via time slicing). I'm not sure so double-check me on that, but I think you need the read lock to also encompass the null check???

Of course keys are unique, so you may just end up with one record anyway in the map (I haven't looked into what object createEvent() returns and how unique it is as a key, based on its equals method), but you'd have duplicate of effort (only need to insert into map once).

Since computeIfAbsent was the issue, you could get away with using an Optional (assuming Java 8 as a minimum version) for null checking without locking??

Anyway, thank you for the quick turnaround on a fix, its appreciated.

commented

You are correct. This is why I shouldn't do fixes while half-asleep...