Skip to content

kotlin.coroutines.jvm.internal.CompletedContinuation cannot be cast to kotlinx.coroutines.internal.DispatchedContinuation #3005

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

Closed
gildor opened this issue Oct 29, 2021 · 18 comments
Assignees

Comments

@gildor
Copy link
Contributor

gildor commented Oct 29, 2021

I have this crash on runtime with Kotlin 1.5.31 and kotlinx.coroutines 1.5.2. I use BOM for Kotlin and corouties with enforcePlatform, so it looks that correct version is used on runtime

It looks exactly the same as #2736 but this issue was closed and fix available in 1.5.2

So I report it separately.

kotlinx.coroutines.CoroutinesInternalError: Fatal exception in coroutines machinery for CancellableContinuation(DispatchedContinuation[Dispatchers.Main.immediate, Continuation at com.bandlab.listmanager.pagination.impl.PaginationListManagerImpl.reload$suspendImpl(PaginationListManagerImpl.kt:223)@ed822fb]){Cancelled}@5d18f18. Please read KDoc to 'handleFatalException' method and report this incident to maintainers
        at kotlinx.coroutines.DispatchedTask.handleFatalException(DispatchedTask.kt:144)
        at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:251)
        at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:161)
        at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:397)
        at kotlinx.coroutines.CancellableContinuationImpl.cancel(CancellableContinuationImpl.kt:183)
        at kotlinx.coroutines.CancellableContinuationImpl.parentCancelled$kotlinx_coroutines_core(CancellableContinuationImpl.kt:190)
        at kotlinx.coroutines.ChildContinuation.invoke(JobSupport.kt:1474)
        at kotlinx.coroutines.JobSupport.completeStateFinalization(JobSupport.kt:318)
        at kotlinx.coroutines.JobSupport.tryFinalizeSimpleState(JobSupport.kt:295)
        at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:856)
        at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:828)
        at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:100)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46)
        at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:234)
        at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:166)
        at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:397)
        at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:431)
        at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:420)
        at kotlinx.coroutines.CancellableContinuationImpl.resumeUndispatched(CancellableContinuationImpl.kt:518)
        at kotlinx.coroutines.android.HandlerContext$scheduleResumeAfterDelay$$inlined$Runnable$1.run(Runnable.kt:19)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loopOnce(Looper.java:201)
        at android.os.Looper.loop(Looper.java:288)
        at android.app.ActivityThread.main(ActivityThread.java:7842)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
     Caused by: java.lang.ClassCastException: kotlin.coroutines.jvm.internal.CompletedContinuation cannot be cast to kotlinx.coroutines.internal.DispatchedContinuation
        at kotlinx.coroutines.CoroutineDispatcher.releaseInterceptedContinuation(CoroutineDispatcher.kt:107)
        at kotlin.coroutines.jvm.internal.ContinuationImpl.releaseIntercepted(ContinuationImpl.kt:118)
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:39)
        at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:234)
        at kotlinx.coroutines.DispatchedTaskKt.resumeUnconfined(DispatchedTask.kt:190)
        at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:161) 
        at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:397) 
        at kotlinx.coroutines.CancellableContinuationImpl.cancel(CancellableContinuationImpl.kt:183) 
        at kotlinx.coroutines.CancellableContinuationImpl.parentCancelled$kotlinx_coroutines_core(CancellableContinuationImpl.kt:190) 
        at kotlinx.coroutines.ChildContinuation.invoke(JobSupport.kt:1474) 
        at kotlinx.coroutines.JobSupport.completeStateFinalization(JobSupport.kt:318) 
        at kotlinx.coroutines.JobSupport.tryFinalizeSimpleState(JobSupport.kt:295) 
        at kotlinx.coroutines.JobSupport.tryMakeCompleting(JobSupport.kt:856) 
        at kotlinx.coroutines.JobSupport.makeCompletingOnce$kotlinx_coroutines_core(JobSupport.kt:828) 
        at kotlinx.coroutines.AbstractCoroutine.resumeWith(AbstractCoroutine.kt:100) 
        at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:46) 
        at kotlinx.coroutines.DispatchedTaskKt.resume(DispatchedTask.kt:234) 
        at kotlinx.coroutines.DispatchedTaskKt.dispatch(DispatchedTask.kt:166) 
        at kotlinx.coroutines.CancellableContinuationImpl.dispatchResume(CancellableContinuationImpl.kt:397) 
        at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl(CancellableContinuationImpl.kt:431) 
        at kotlinx.coroutines.CancellableContinuationImpl.resumeImpl$default(CancellableContinuationImpl.kt:420) 
        at kotlinx.coroutines.CancellableContinuationImpl.resumeUndispatched(CancellableContinuationImpl.kt:518) 
        at kotlinx.coroutines.android.HandlerContext$scheduleResumeAfterDelay$$inlined$Runnable$1.run(Runnable.kt:19) 
        at android.os.Handler.handleCallback(Handler.java:938) 
        at android.os.Handler.dispatchMessage(Handler.java:99) 
        at android.os.Looper.loopOnce(Looper.java:201) 
        at android.os.Looper.loop(Looper.java:288) 
        at android.app.ActivityThread.main(ActivityThread.java:7842) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003) 
@qwwdfsad
Copy link
Member

Hi, is there any chance you have a semi-stable reproducer or know the exact pattern of code that triggers this bug?

This is indeed a bug in one of the most concurrent parts of kotlinx.coroutines and we're chasing it without any success yet

@gildor
Copy link
Contributor Author

gildor commented Oct 29, 2021

It crashes in 100% cases, this is quite a complex code, with a few linked scopes when suspend function is passed as lambda to be called on another scope
For now, I work around it by replacing suspend lambda with standard lambda and just launching a new coroutine on a separate scope.

I can try to reproduce, but not sure that it would be easy

@qwwdfsad
Copy link
Member

It crashes in 100% cases
I can try to reproduce, but not sure that it would be easy

That's really great, it would be drastically helpful for us if you could share it in any form, public or private.
Looking forward to hearing from you!

@nomisRev
Copy link

nomisRev commented Oct 30, 2021

I just ran into this issues as well. It's reprducible, but only after x invocations of th property based testing.

Here is the public repo, and a reference to the two failing tests:
https://github.com/nomisRev/Continuation/blob/020b0c0e15786b23927fb94cd8833b6d2230b240/src/commonTest/kotlin/ContSpec.kt#L103

Hope this helps 👍

@qwwdfsad
Copy link
Member

qwwdfsad commented Nov 1, 2021

Thanks @nomisRev! I can verify it's reproducible.

I'm not really familiar with kotest, does it require a special plugin? Because I can run tests from your project only as Gradle task, but cannot e.g. debug it from IDEA

@qwwdfsad
Copy link
Member

qwwdfsad commented Nov 1, 2021

@nomisRev alas this bug has nothing to do with the original one, the reproducer is not using the piece of machinery that is prone to the actual bug.

In your case things are much simpler -- when shift is invoked, the outer continuation is resumed twice.

I would suspect the following function in your implementation:

return suspendCoroutineUninterceptedOrReturn { contB ->
    contB.resumeWithException(ShiftCancellationException(token))
    COROUTINE_SUSPENDED
}

You first resume the contB and then return COROUTINE_SUSPENDED, effectively confusing the caller.
suspendCoroutineUninterceptedOrReturn does not have any additional guards against such misuses (that's why it is hidden in the first place), thus leading to undefined and racy behaviour.

I suggest using suspendCoroutine instead in your implementation.

@nomisRev
Copy link

nomisRev commented Nov 1, 2021

Okay, I see. Thank you so much for the pointer @qwwdfsad! Changing it, and solved the problem! My apologies, I hoped I was able to help with a reproduceable example.

I guess since I want to avoid the call to intercepted() and wrapping in SafeContinuation I should have just used throw ShiftCancellationException(token) to begin with, since it needs to cancel the coroutine shift was called to support structured concurrency test.

Can I ask you an unrelated question about Kotlin coroutines cancellation? documented here.

@qwwdfsad
Copy link
Member

qwwdfsad commented Nov 1, 2021

Can I ask you an unrelated question about Kotlin coroutines cancellation? documented here.

Sure, you can reach me out in public Slack (Vsevolod Tolstopyatov [JB]). I'm out of the context of what this code actually does and in need of some details to actually answer that

@joharei
Copy link

joharei commented Dec 9, 2021

I'm also encountering this in my production app, but haven't been able to reproduce it, as it's happening in some bluetooth communication code that's hard to test at scale.

Stacktrace
Fatal Exception: kotlin.NotImplementedError: Fatal exception in coroutines machinery for DispatchedContinuation[g0@e10a02f, Continuation at com.juul.kable.AndroidPeripheral.write(Peripheral.kt)@55aed1a]. Please read KDoc to 'handleFatalException' method and report this incident to maintainers
       at kotlinx.coroutines.DispatchedTask.handleFatalException(DispatchedTask.java:144)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.java:115)
       at androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch(AndroidUiDispatcher.java:81)
       at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(AndroidUiDispatcher.java:41)
       at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.run(AndroidUiDispatcher.java:57)
       at android.os.Handler.handleCallback(Handler.java:938)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:247)
       at android.app.ActivityThread.main(ActivityThread.java:8656)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
    Caused by java.lang.ClassCastException: kotlin.coroutines.jvm.internal.CompletedContinuation cannot be cast to kotlinx.coroutines.internal.DispatchedContinuation
       at kotlinx.coroutines.CoroutineDispatcher.releaseInterceptedContinuation(CoroutineDispatcher.java:107)
       at kotlin.coroutines.jvm.internal.ContinuationImpl.releaseIntercepted(ContinuationImpl.java:118)
       at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(BaseContinuationImpl.java:39)
       at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.java:233)
       at androidx.compose.ui.platform.AndroidUiDispatcher.performTrampolineDispatch(AndroidUiDispatcher.java:81)
       at androidx.compose.ui.platform.AndroidUiDispatcher.access$performTrampolineDispatch(AndroidUiDispatcher.java:41)
       at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.run(AndroidUiDispatcher.java:57)
       at android.os.Handler.handleCallback(Handler.java:938)
       at android.os.Handler.dispatchMessage(Handler.java:99)
       at android.os.Looper.loop(Looper.java:247)
       at android.app.ActivityThread.main(ActivityThread.java:8656)
       at java.lang.reflect.Method.invoke(Method.java)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)

Having a look at previous issues #2719 and #2736 suggests that this could be caused by using inline suspend functions or inline classes, and both are used in the function where this is happening.

I found this issue, that seems pretty similar to me. I can confirm that the reproducer in the comments still crashes on Kotlin 1.6.0 with coroutines 1.6.0-RC.

@Xlopec
Copy link

Xlopec commented Jan 4, 2022

I'm still experiencing this issue, I filled a bug and attached a small reproducer. Recently I tried updating the project to 1.6.10 with coroutines 1.6.0 and eap Ktor... still no luck

@qwwdfsad
Copy link
Member

@Xlopec thanks for writing here in addition to YT! I've reproduced your problem, it seems to be on the edge of kotlinx.coroutines and Ktor's mechanism of reusing continuations. I'm figuring it out

@qwwdfsad qwwdfsad self-assigned this Jan 17, 2022
@qwwdfsad
Copy link
Member

I've found the root cause: https://youtrack.jetbrains.com/issue/KT-50832

As a workaround, please avoid method-references to suspend inline functions and use a plain lambda instead (e.g. ::WebWebSocketSession -> { WebSocketSession(it) }

@yangwuan55
Copy link

any update for this?

@yangwuan55
Copy link

I do this code and has same problem in my android project,but I do the single test for the same code the error is gone,hope for a quick settlement.

launch(Dispatchers.Main) {
        //a suspend block from function params
        block()
}

@yangwuan55
Copy link

any update?If cant resolve this issue,I have to put away the coroutines.

@yangwuan55
Copy link

I've found the root cause: https://youtrack.jetbrains.com/issue/KT-50832

As a workaround, please avoid method-references to suspend inline functions and use a plain lambda instead (e.g. ::WebWebSocketSession -> { WebSocketSession(it) }

I don't use ktor,but I have the same bug,If any update please reply,Thank you very much!

@qwwdfsad
Copy link
Member

qwwdfsad commented Jun 7, 2022

Unfortunately, there are no updates apart from the ones in KT-50832: it will be fixed in 1.7.20, until then it's better to avoid a problematic pattern in your code base.

Also, closing as compiler issue.

@qwwdfsad qwwdfsad closed this as completed Jun 7, 2022
@yangwuan55
Copy link

Unfortunately, there are no updates apart from the ones in KT-50832: it will be fixed in 1.7.20, until then it's better to avoid a problematic pattern in your code base.

Also, closing as compiler issue.

So my issue is another?But how can I do can avoid?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants