Kamel-Media / Kamel

Kotlin asynchronous media loading and caching library for Compose.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Concurrent modification exception in Disk Cache

lumstep opened this issue · comments

I'm using KamelImage in LazyVerticalGrid and encountering this crash when I try to scroll very quickly.

FATAL EXCEPTION: DefaultDispatcher-worker-25
java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:760)
at java.util.LinkedHashMap$LinkedValueIterator.next(LinkedHashMap.java:787)
at io.kamel.core.cache.disk.DiskLruCache.removeOldestEntry(DiskLruCache.kt:613)
at io.kamel.core.cache.disk.DiskLruCache.trimToSize(DiskLruCache.kt:606)
at io.kamel.core.cache.disk.DiskLruCache.access$trimToSize(DiskLruCache.kt:91)
at io.kamel.core.cache.disk.DiskLruCache$launchCleanup$1$1.invokeSuspend(DiskLruCache.kt:652)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@dfa9a16, Dispatchers.IO]

related to #66

try 0.9.0 lmk if you have any problems.

FATAL EXCEPTION: DefaultDispatcher-worker-7
                                                                                                    Process: com.sample.test PID: 16005
                                                                                                    java.util.ConcurrentModificationException
                                                                                                    	at java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:760)
                                                                                                    	at java.util.LinkedHashMap$LinkedValueIterator.next(LinkedHashMap.java:787)
                                                                                                    	at co.touchlab.stately.collections.ConcurrentMutableIterator$next$1.invoke(ConcurrentMutableCollection.kt:54)
                                                                                                    	at co.touchlab.stately.collections.ConcurrentMutableIterator.next(ConcurrentMutableCollection.kt:85)
                                                                                                    	at io.kamel.core.cache.disk.DiskLruCache.removeOldestEntry(DiskLruCache.kt:615)
                                                                                                    	at io.kamel.core.cache.disk.DiskLruCache.trimToSize(DiskLruCache.kt:608)
                                                                                                    	at io.kamel.core.cache.disk.DiskLruCache.access$trimToSize(DiskLruCache.kt:93)
                                                                                                    	at io.kamel.core.cache.disk.DiskLruCache$launchCleanup$1$1.invokeSuspend(DiskLruCache.kt:654)
                                                                                                    	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
                                                                                                    	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
                                                                                                    	at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
                                                                                                    	at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
                                                                                                    	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
                                                                                                    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
                                                                                                    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
                                                                                                    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
                                                                                                    	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@58ddac0, Dispatchers.IO]
[versions]
kamel = "0.9.0"
[libraries]
kamel = { module = "media.kamel:kamel-image", version.ref = "kamel" }

Same issue @luca992 even in LazyColumn/Row/Grid

FATAL EXCEPTION: DefaultDispatcher-worker-7
                                                                                                    Process: com.sample.test PID: 16005
                                                                                                    java.util.ConcurrentModificationException
                                                                                                    	at java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:760)
                                                                                                    	at java.util.LinkedHashMap$LinkedValueIterator.next(LinkedHashMap.java:787)
                                                                                                    	at co.touchlab.stately.collections.ConcurrentMutableIterator$next$1.invoke(ConcurrentMutableCollection.kt:54)
                                                                                                    	at co.touchlab.stately.collections.ConcurrentMutableIterator.next(ConcurrentMutableCollection.kt:85)
                                                                                                    	at io.kamel.core.cache.disk.DiskLruCache.removeOldestEntry(DiskLruCache.kt:615)
                                                                                                    	at io.kamel.core.cache.disk.DiskLruCache.trimToSize(DiskLruCache.kt:608)
                                                                                                    	at io.kamel.core.cache.disk.DiskLruCache.access$trimToSize(DiskLruCache.kt:93)
                                                                                                    	at io.kamel.core.cache.disk.DiskLruCache$launchCleanup$1$1.invokeSuspend(DiskLruCache.kt:654)
                                                                                                    	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
                                                                                                    	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
                                                                                                    	at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
                                                                                                    	at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
                                                                                                    	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
                                                                                                    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
                                                                                                    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
                                                                                                    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
                                                                                                    	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@58ddac0, Dispatchers.IO]
[versions]
kamel = "0.9.0"
[libraries]
kamel = { module = "media.kamel:kamel-image", version.ref = "kamel" }

Same issue @luca992 even in LazyColumn/Row/Grid

I guess it won't be an easy fix, as clearly stately isn't helping. If you can fork and modify the sample project in the project with an example that causes it in a somewhat reproducible way, that would be a big help.

FATAL EXCEPTION: DefaultDispatcher-worker-7
                                                                                                    Process: com.sample.test PID: 16005
                                                                                                    java.util.ConcurrentModificationException
                                                                                                    	at java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:760)
                                                                                                    	at java.util.LinkedHashMap$LinkedValueIterator.next(LinkedHashMap.java:787)
                                                                                                    	at co.touchlab.stately.collections.ConcurrentMutableIterator$next$1.invoke(ConcurrentMutableCollection.kt:54)
                                                                                                    	at co.touchlab.stately.collections.ConcurrentMutableIterator.next(ConcurrentMutableCollection.kt:85)
                                                                                                    	at io.kamel.core.cache.disk.DiskLruCache.removeOldestEntry(DiskLruCache.kt:615)
                                                                                                    	at io.kamel.core.cache.disk.DiskLruCache.trimToSize(DiskLruCache.kt:608)
                                                                                                    	at io.kamel.core.cache.disk.DiskLruCache.access$trimToSize(DiskLruCache.kt:93)
                                                                                                    	at io.kamel.core.cache.disk.DiskLruCache$launchCleanup$1$1.invokeSuspend(DiskLruCache.kt:654)
                                                                                                    	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
                                                                                                    	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
                                                                                                    	at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
                                                                                                    	at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
                                                                                                    	at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
                                                                                                    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
                                                                                                    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
                                                                                                    	at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
                                                                                                    	Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@58ddac0, Dispatchers.IO]
[versions]
kamel = "0.9.0"
[libraries]
kamel = { module = "media.kamel:kamel-image", version.ref = "kamel" }

Same issue @luca992 even in LazyColumn/Row/Grid

I guess it won't be an easy fix, as clearly stately isn't helping. If you can fork and modify the sample project in the project with an example that causes it in a somewhat reproducible way, that would be a big help.

Just add a random LazyColumn/Row/Grid with lots of elements that contain images and try to scroll really fast, it'll crash all the time.

I'll try to add a sample.

Yes, the problem is still reproducible with the following stack trace:
java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:760)
at java.util.LinkedHashMap$LinkedValueIterator.next(LinkedHashMap.java:787)
at co.touchlab.stately.collections.ConcurrentMutableIterator$next$1.invoke(ConcurrentMutableCollection.kt:54)
at co.touchlab.stately.collections.ConcurrentMutableIterator.next(ConcurrentMutableCollection.kt:85)
at io.kamel.core.cache.disk.DiskLruCache.removeOldestEntry(DiskLruCache.kt:615)
at io.kamel.core.cache.disk.DiskLruCache.trimToSize(DiskLruCache.kt:608)
at io.kamel.core.cache.disk.DiskLruCache.access$trimToSize(DiskLruCache.kt:93)
at io.kamel.core.cache.disk.DiskLruCache$launchCleanup$1$1.invokeSuspend(DiskLruCache.kt:654)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:108)
at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:115)
at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:103)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:584)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:793)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:697)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:684)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@eeb19e, Dispatchers.IO]

But I guess that issue already exist: touchlab/Stately#105
I hope once touchlab can fix the problem, you can update the library and republish kamel.

released update 0.9.1 with @kamiox PR. Hopefully that fixes the issue. I'm going to close this but if it still is occurring just reply here and I'll re-open it.

I'm using KamelImage in LazyColumn, and this crash in release versions 0.9.1 and 0.9.2 still exist. Previous version that i use in our project 0.7.0 is ok.

java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:775)
at java.util.LinkedHashMap$LinkedValueIterator.next(LinkedHashMap.java:803)
at co.touchlab.stately.collections.IsoMutableIterator$next$1.invoke(IsoMutableIterator.kt:9)
at co.touchlab.stately.collections.IsoMutableIterator$next$1.invoke(IsoMutableIterator.kt:9)
at co.touchlab.stately.isolate.IsolateState$access$1.invoke(IsoState.kt:30)
at co.touchlab.stately.isolate.BackgroundStateRunner.stateRun$lambda$0(BackgroundStateRunner.kt:13)
at co.touchlab.stately.isolate.BackgroundStateRunner.$r8$lambda$hxiDVCnhiQcOCqU-a_lP4-OikbU(Unknown Source:0)
at co.touchlab.stately.isolate.BackgroundStateRunner$$ExternalSyntheticLambda0.call(Unknown Source:2)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [androidx.compose.runtime.PausableMonotonicFrameClock@d9fbdf6, androidx.compose.ui.platform.MotionDurationScaleImpl@b2905f7, StandaloneCoroutine{Cancelling}@452fc64, AndroidUiDispatcher@9941ecd]

I'm using KamelImage in LazyColumn, and this crash in release versions 0.9.1 and 0.9.2 still exist. Previous version that i use in our project 0.7.0 is ok.

java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextNode(LinkedHashMap.java:775)
at java.util.LinkedHashMap$LinkedValueIterator.next(LinkedHashMap.java:803)
at co.touchlab.stately.collections.IsoMutableIterator$next$1.invoke(IsoMutableIterator.kt:9)
at co.touchlab.stately.collections.IsoMutableIterator$next$1.invoke(IsoMutableIterator.kt:9)
at co.touchlab.stately.isolate.IsolateState$access$1.invoke(IsoState.kt:30)
at co.touchlab.stately.isolate.BackgroundStateRunner.stateRun$lambda$0(BackgroundStateRunner.kt:13)
at co.touchlab.stately.isolate.BackgroundStateRunner.$r8$lambda$hxiDVCnhiQcOCqU-a_lP4-OikbU(Unknown Source:0)
at co.touchlab.stately.isolate.BackgroundStateRunner$$ExternalSyntheticLambda0.call(Unknown Source:2)
Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [androidx.compose.runtime.PausableMonotonicFrameClock@d9fbdf6, androidx.compose.ui.platform.MotionDurationScaleImpl@b2905f7, StandaloneCoroutine{Cancelling}@452fc64, AndroidUiDispatcher@9941ecd]

@1Avalanche 😓 might have to drop use of cache4k for the LruCache as it also is using stately and this issue hasn't been resolved

@1Avalanche try 0.9.3 just published. Cache4k added a potential fix for ConcurrentModificationException on jvm

lmk how it goes.