Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IllegalStateException: Method should be called from AWT event dispatch thread #4472

Closed
alexzhirkevich opened this issue Mar 12, 2024 · 4 comments
Labels
bug Something isn't working submitted

Comments

@alexzhirkevich
Copy link
Contributor

alexzhirkevich commented Mar 12, 2024

Sometimes when a new composable is added/removed from the screen i get this crash. It happens randomly while preforming the same actions.

Unfortunately i'm unable to make a small reproducer.
There is a SnapshotStateMap that being filled from the coroutines in a composition coroutine scope without any concurrent modifications. No error happens if items are added syncronously.

Are snapshot collections not allowed to read/modify from a coroutine?

val scope = rememberCoroutineScope()

// this sometimes throws error. no fast double clicks or something
// running block with `Snapshot.withoutReadObservation` didn't help
onClick = {
    scope.launch {
         mutex.withLock { // just to make sure it is not a concurrent modification problem
              readSomeComposableState()
              readSomeValuesFromMap()
              addValueToMap()
        }
    }
}

/// this doesn't throw error
onClick = {
         readSomeComposableState()
         readSomeValuesFromMap()
         addValueToMap()
}
java.lang.IllegalStateException: Method should be called from AWT event dispatch thread at org.jetbrains.skiko.SkiaLayer.needRedraw(SkiaLayer.awt.kt:517)
 at androidx.compose.ui.scene.skia.WindowSkiaLayerComponent.onComposeInvalidation(WindowSkiaLayerComponent.desktop.kt:110) at androidx.compose.ui.scene.ComposeSceneMediator.onComposeInvalidation(ComposeSceneMediator.desktop.kt:464)
 at androidx.compose.ui.scene.ComposeContainer$createComposeScene$1.invoke(ComposeContainer.desktop.kt:254) at androidx.compose.ui.scene.ComposeContainer$createComposeScene$1.invoke(ComposeContainer.desktop.kt:254)
 at androidx.compose.ui.scene.BaseComposeScene.invalidateIfNeeded(BaseComposeScene.skiko.kt:100) at androidx.compose.ui.scene.BaseComposeScene$snapshotInvalidationTracker$1.invoke(BaseComposeScene.skiko.kt:57)
 at androidx.compose.ui.scene.BaseComposeScene$snapshotInvalidationTracker$1.invoke(BaseComposeScene.skiko.kt:57) at androidx.compose.ui.node.CommandList.add(SnapshotInvalidationTracker.skiko.kt:130)
 at androidx.compose.ui.node.SnapshotInvalidationTracker$snapshotObserver$1.invoke(SnapshotInvalidationTracker.skiko.kt:75) at androidx.compose.ui.node.SnapshotInvalidationTracker$snapshotObserver$1.invoke(SnapshotInvalidationTracker.skiko.kt:71)
 at androidx.compose.runtime.snapshots.SnapshotStateObserver.sendNotifications(SnapshotStateObserver.kt:83) at androidx.compose.runtime.snapshots.SnapshotStateObserver.access$sendNotifications(SnapshotStateObserver.kt:43)
 at androidx.compose.runtime.snapshots.SnapshotStateObserver$applyObserver$1.invoke(SnapshotStateObserver.kt:50) at androidx.compose.runtime.snapshots.SnapshotStateObserver$applyObserver$1.invoke(SnapshotStateObserver.kt:48)
 at androidx.compose.runtime.snapshots.SnapshotKt.advanceGlobalSnapshot(Snapshot.kt:1816) at androidx.compose.runtime.snapshots.SnapshotKt.takeNewSnapshot(Snapshot.kt:1834)
 at androidx.compose.runtime.snapshots.SnapshotKt.access$takeNewSnapshot(Snapshot.kt:1) at androidx.compose.runtime.snapshots.GlobalSnapshot.takeNestedSnapshot(Snapshot.kt:1333)
 at androidx.compose.runtime.snapshots.Snapshot$Companion.takeSnapshot(Snapshot.kt:330) at androidx.compose.runtime.SnapshotStateKt__SnapshotFlowKt$snapshotFlow$1.invokeSuspend(SnapshotFlow.kt:162)
 at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:104)
 at kotlinx.coroutines.internal.LimitedDispatcher$Worker.run(LimitedDispatcher.kt:111) at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:99)
 at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:585) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:802)
 at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:706) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:693)

Affected platforms

  • Desktop (Windows, Linux, macOS)

Versions

  • Kotlin version*: 1.9.20
  • Compose Multiplatform version*: 1.6.0
  • OS version(s)* (required for Desktop and iOS issues): Win 10
  • JDK (for desktop issues): JBR 17
@alexzhirkevich alexzhirkevich added bug Something isn't working submitted labels Mar 12, 2024
@eymar
Copy link
Collaborator

eymar commented Mar 13, 2024

@alexzhirkevich I see you close this one. Did you find a reason?

@alexzhirkevich
Copy link
Contributor Author

alexzhirkevich commented Mar 13, 2024

@eymar No. I found this thread and decided that it is better not to interact with state objects in a concurrent way and just refactored code to work with it synchronously. The only difference that in that thread the work was done not in the main thread. In my case dispatcher was't making any difference. If you want to dive in it i can try to make a repducer, but it probably will be large

@alexzhirkevich
Copy link
Contributor Author

The code runs perfectly fine on iOS and Android, so probably there is really something wrong with desktop

@alexzhirkevich
Copy link
Contributor Author

Also it doesn't crash if launched in Unconfirmed dispatcher but does in Main dispatcher 🤔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working submitted
Projects
None yet
Development

No branches or pull requests

2 participants