Kamel-Media / Kamel

Kotlin asynchronous media loading and caching library for Compose.
Apache License 2.0
592 stars 23 forks source link

Concurrent modification exception in Disk Cache #75

Closed lumstep closed 6 months ago

lumstep commented 7 months ago

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]

luca992 commented 7 months ago

related to #66

luca992 commented 7 months ago

try 0.9.0 lmk if you have any problems.

FunkyMuse commented 7 months ago
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

luca992 commented 7 months ago
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.

FunkyMuse commented 7 months ago
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.

lumstep commented 6 months ago

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: https://github.com/touchlab/Stately/issues/105 I hope once touchlab can fix the problem, you can update the library and republish kamel.

luca992 commented 6 months ago

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.

1Avalanche commented 4 months ago

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]
luca992 commented 4 months ago

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

luca992 commented 4 months ago

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

lmk how it goes.