Platform: iOS, org.jetbrains.kotlinx:kotlinx-coroutines-core-iosarm64
Version: 1.3.5-native-mt
Example:
class IssueReproduce: CoroutineScope {
private val dispatcher = DispatchersProvider.dispatcherUi
private val job = SuperviserJob()
private val someApi = SomeApi()
override val coroutineContext: CoroutineContext
get() = dispatcher + job
fun performApiCall(callback: (SomeDataClass) -> Unit) {
launch(coroutineContext) {
val response = someApi.someMethod()
callback(response)
}
}
}
/* ... */
actual object DispatchersProvider {
actual val dispatcherUi: CoroutineDispatcher = IosMainDispatcher
}
private object IosMainDispatcher : CoroutineDispatcher() {
override fun dispatch(context: CoroutineContext, block: Runnable) {
dispatch_async(dispatch_get_main_queue(), block::run)
}
}
/* ... */
class SomeApi {
private val client: HttpClient = /* ... */
suspend fun someMethod(): SomeDataClass {
return client.get { /* ... */ }
}
}
If someApi.someMethod() is successful, all is ok.
But when (performApiCall called from iOS, and) someApi.someMethod() throws some exception, then below crash happens:
Uncaught Kotlin exception: kotlinx.coroutines.CoroutinesInternalError: Fatal exception in coroutines machinery for DispatchedContinuation[IosMainDispatcher@7c947c98, Continuation @ $getStories$lambda-0COROUTINE$6]. Please read KDoc to 'handleFatalException' method and report this incident to maintainers
at 0 ExampleAppCommon 0x00000001030047a8 kfun:kotlin.Error.<init>(kotlin.String?;kotlin.Throwable?)kotlin.Error + 116
at 1 ExampleAppCommon 0x0000000103134a20 kfun:kotlinx.coroutines.CoroutinesInternalError.<init>(kotlin.String;kotlin.Throwable)kotlinx.coroutines.CoroutinesInternalError + 116
at 2 ExampleAppCommon 0x0000000103170408 kfun:kotlinx.coroutines.DispatchedTask.handleFatalException$kotlinx-coroutines-core(kotlin.Throwable?;kotlin.Throwable?) + 708
at 3 ExampleAppCommon 0x00000001031700e0 kfun:kotlinx.coroutines.DispatchedTask.run() + 3024
at 4 ExampleAppCommon 0x00000001033654d8 kfun:com.example.presentation.IosMainDispatcher.$run$FUNCTION_REFERENCE$21.invoke#internal + 116
at 5 ExampleAppCommon 0x0000000103365538 kfun:com.example.presentation.IosMainDispatcher.$run$FUNCTION_REFERENCE$21.$<bridge-UNN>invoke()#internal + 64
at 6 ExampleAppCommon 0x000000010336574c _4e6967687453746f7279436f6d6d6f6e_knbridge9 + 188
at 7 libdispatch.dylib 0x0000000103bedd10 _dispatch_call_block_and_release + 32
at 8 libdispatch.dylib 0x0000000103bef18c _dispatch_client_callout + 20
at 9 libdispatch.dylib 0x0000000103bfdd14 _dispatch_main_queue_callback_4CF + 996
at 10 CoreFoundation 0x00000001b483741c 9624AAFD-5437-3772-A507-0F357875808D + 709660
at 11 CoreFoundation 0x00000001b4832034 9624AAFD-5437-3772-A507-0F357875808D + 688180
at 12 CoreFoundation 0x00000001b4831660 CFRunLoopRunSpecific + 480
at 13 GraphicsServices 0x00000001bec42604 GSEventRunModal + 164
at 14 UIKitCore 0x00000001b8a0615c UIApplicationMain + 1944
at 15 Example App 0x00000001024f205c main + 80
at 16 libdyld.dylib 0x00000001b46ad1ec 95B366E7-F5BD-3308-9416-24B35999029B + 4588
Caused by: kotlin.ClassCastException: kotlin.coroutines.native.internal.CompletedContinuation cannot be cast to kotlinx.coroutines.DispatchedContinuation
at 0 ExampleAppCommon 0x000000010300b1bc kfun:kotlin.Throwable.<init>(kotlin.String?)kotlin.Throwable + 92
at 1 ExampleAppCommon 0x000000010300401c kfun:kotlin.Exception.<init>(kotlin.String?)kotlin.Exception + 88
at 2 ExampleAppCommon 0x0000000103003ae0 kfun:kotlin.RuntimeException.<init>(kotlin.String?)kotlin.RuntimeException + 88
at 3 ExampleAppCommon 0x0000000103004a8c kfun:kotlin.ClassCastException.<init>(kotlin.String?)kotlin.ClassCastException + 88
at 4 ExampleAppCommon 0x000000010304f680 ThrowClassCastException + 636
at 5 ExampleAppCommon 0x000000010312b444 kfun:kotlinx.coroutines.CoroutineDispatcher.releaseInterceptedContinuation(kotlin.coroutines.Continuation<#STAR>) + 196
at 6 ExampleAppCommon 0x00000001030292b4 kfun:kotlin.coroutines.native.internal.ContinuationImpl.releaseIntercepted() + 696
at 7 ExampleAppCommon 0x0000000103029844 kfun:kotlin.coroutines.native.internal.BaseContinuationImpl.resumeWith(kotlin.Result<kotlin.Any?>) + 1008
at 8 ExampleAppCommon 0x000000010316fdfc kfun:kotlinx.coroutines.DispatchedTask.run() + 2284
at 9 ExampleAppCommon 0x00000001033654d8 kfun:com.example.mobile.IosMainDispatcher.$run$FUNCTION_REFERENCE$21.invoke#internal + 116
at 10 ExampleAppCommon 0x0000000103365538 kfun:com.example.mobile.IosMainDispatcher.$run$FUNCTION_REFERENCE$21.$<bridge-UNN>invoke()#internal + 64
at 11 ExampleAppCommon 0x000000010336574c _4e6967687453746f7279436f6d6d6f6e_knbridge9 + 188
at 12 libdispatch.dylib 0x0000000103bedd10 _dispatch_call_block_and_release + 32
at 13 libdispatch.dylib 0x0000000103bef18c _dispatch_client_callout + 20
at 14 libdispatch.dylib 0x0000000103bfdd14 _dispatch_main_queue_callback_4CF + 996
at 15 CoreFoundation 0x00000001b483741c 9624AAFD-5437-3772-A507-0F357875808D + 709660
at 16 CoreFoundation 0x00000001b4832034 9624AAFD-5437-3772-A507-0F357875808D + 688180
at 17 CoreFoundation 0x00000001b4831660 CFRunLoopRunSpecific + 480
at 18 GraphicsServices 0x00000001bec42604 GSEventRunModal + 164
at 19 UIKitCore 0x00000001b8a0615c UIApplicationMain + 1944
at 20 Example App 0x00000001024f205c main + 80
at 21 libdyld.dylib 0x00000001b46ad1ec 95B366E7-F5BD-3308-9416-24B35999029B + 4588
(lldb)
How to fix this: simply wrap someApi.someMethod() call with try-catch, or use the CoroutineExceptionHandler. Yea, the issue persists only when there are some uncaught exceptions, but I think I want to see the exception that was thrown, not this exception which not refers to my code :)
On -native-mt version you cannot implement IosMainDispatcher this way. It is not supported at the moment. You should use Dispatchers.Main instead.
Does it help?
@elizarov Idk why I closed this :)
There is the same issue with Dispatchers.Main, and the key question was about the CompletedContinuation cannot be cast to DispatchedContinuation and how to get the original exception's stack trace on iOS :)
The only part is changed is DispatchedContinuation[IosMainDispatcher@7c947c98, it is changed to DispatchedContinuation[MainDispatcher.
Maybe, the stack trace is too long, and in the Xcode I can see only the last two elements, and the original exception is simply deeper? So, how to see it?
If I catch the error in catch(e: Throwable) { /* here */ }, I can only see the com.package.Exception: message, and not the stack trace.
Do you have a short reproducer in native-mt branch using a standard Dispatchers.Main?
@elizarov, using coroutines 1.3.5-native-mt, this code
CoroutineScope(Dispatchers.Main).launch {
val deferredResult = CoroutineScope(Dispatchers.Default).async {
val response = HttpClient().get<String> {
url("https://www.google.com")
}
// process response and generate result
val result = /* ... */ response
result
}
println(deferredResult.await())
}
produces the same kotlin.ClassCastException: kotlin.coroutines.native.internal.CompletedContinuation cannot be cast to kotlinx.coroutines.DispatchedContinuation when called from iOS main thread.
Isn't this code supposed to work, since both Dispatchers.Main and (a single background thread version of) Dispatchers.Default are available for iOS with 1.3.5-native-mt (as stated at https://github.com/Kotlin/kotlinx.coroutines/blob/native-mt/kotlin-native-sharing.md)?
Same thing happens with this code
CoroutineScope(Dispatchers.Main).launch {
val result = withContext(Dispatchers.Default) {
val response = HttpClient().get<String> {
url("https://www.google.com")
}
// process response and generate result
val result = /* ... */ response
result
}
println(result)
}
PS: I think https://github.com/ktorio/ktor/issues/1540 is a related issue
I am experiencing this issue as well. Unfortunately, I do not have a consistent way to reproduce it yet.
I am using Coroutines 1.3.5-native-mt. All of my iOS code uses Dispatchers.Main at the moment.
Xcode shows the following:
Uncaught Kotlin exception: kotlinx.coroutines.CoroutinesInternalError: Fatal exception in coroutines machinery for DispatchedContinuation[MainDispatcher, Continuation @ $awaitSuspendCOROUTINE$1222]. Please read KDoc to 'handleFatalException' method and report this incident to maintainers
at 0 common 0x0000000107354d94 kfun:kotlin.Error.<init>(kotlin.String?;kotlin.Throwable?)kotlin.Error + 116
at 1 common 0x000000010744e69c kfun:kotlinx.coroutines.CoroutinesInternalError.<init>(kotlin.String;kotlin.Throwable)kotlinx.coroutines.CoroutinesInternalError + 116
at 2 common 0x00000001074cbc6c kfun:kotlinx.coroutines.DispatchedTask.handleFatalException$kotlinx-coroutines-core(kotlin.Throwable?;kotlin.Throwable?) + 708
at 3 common 0x00000001074cb944 kfun:kotlinx.coroutines.DispatchedTask.run() + 3024
at 4 common 0x0000000107505d10 kfun:kotlinx.coroutines.DarwinMainDispatcher.dispatch$lambda-0#internal + 112
at 5 common 0x00000001075060d0 kfun:kotlinx.coroutines.DarwinMainDispatcher.$dispatch$lambda-0$FUNCTION_REFERENCE$543.invoke#internal + 64
at 6 common 0x0000000107506130 kfun:kotlinx.coroutines.DarwinMainDispatcher.$dispatch$lambda-0$FUNCTION_REFERENCE$543.$<bridge-UNN>invoke()#internal + 64
at 7 common 0x00000001075071bc _6b6f746c696e782d636f726f7574696e65732d636f7265_knbridge828 + 188
at 8 libdispatch.dylib 0x000000010a9bdd10 _dispatch_call_block_and_release + 32
at 9 libdispatch.dylib 0x000000010a9bf18c _dispatch_client_callout + 20
at 10 libdispatch.dylib 0x000000010a9cdd14 _dispatch_main_queue_callback_4CF + 996
at 11 CoreFoundation 0x000000018d38f6b0 AF42303F-57B6-3C11-8F18-8E80ABF7D886 + 710320
at 12 CoreFoundation 0x000000018d38a2c8 AF42303F-57B6-3C11-8F18-8E80ABF7D886 + 688840
at 13 CoreFoundation 0x000000018d3898f4 CFRunLoopRunSpecific + 480
at 14 GraphicsServices 0x00000001977a0604 GSEventRunModal + 164
at 15 UIKitCore 0x000000019155d358 UIApplicationMain + 1944
at 16 HueEssentials-dev 0x0000000104902414 main + 80
at 17 libdyld.dylib 0x000000018d2052dc 322C4E05-D0CF-33F5-B996-CE5C67DF59B6 + 4828
Caused by: kotlin.ClassCastException: kotlin.coroutines.native.internal.CompletedContinuation cannot be cast to kotlinx.coroutines.DispatchedContinuation
at 0 common 0x000000010735b4e0 kfun:kotlin.Throwable.<init>(kotlin.String?)kotlin.Throwable + 92
at 1 common 0x0000000107354608 kfun:kotlin.Exception.<init>(kotlin.String?)kotlin.Exception + 88
at 2 common 0x0000000107354044 kfun:kotlin.RuntimeException.<init>(kotlin.String?)kotlin.RuntimeException + 88
at 3 common 0x0000000107355078 kfun:kotlin.ClassCastException.<init>(kotlin.String?)kotlin.ClassCastException + 88
at 4 common 0x00000001073a394c ThrowClassCastException + 636
at 5 common 0x000000010744490c kfun:kotlinx.coroutines.CoroutineDispatcher.releaseInterceptedContinuation(kotlin.coroutines.Continuation<#STAR>) + 196
at 6 common 0x000000010737ae8c kfun:kotlin.coroutines.native.internal.ContinuationImpl.releaseIntercepted() + 696
at 7 common 0x000000010737b41c kfun:kotlin.coroutines.native.internal.BaseContinuationImpl.resumeWith(kotlin.Result<kotlin.Any?>) + 1008
at 8 common 0x00000001074cb660 kfun:kotlinx.coroutines.DispatchedTask.run() + 2284
at 9 common 0x0000000107505d10 kfun:kotlinx.coroutines.DarwinMainDispatcher.dispatch$lambda-0#internal + 112
at 10 common 0x00000001075060d0 kfun:kotlinx.coroutines.DarwinMainDispatcher.$dispatch$lambda-0$FUNCTION_REFERENCE$543.invoke#internal + 64
at 11 common 0x0000000107506130 kfun:kotlinx.coroutines.DarwinMainDispatcher.$dispatch$lambda-0$FUNCTION_REFERENCE$543.$<bridge-UNN>invoke()#internal + 64
at 12 common 0x00000001075071bc _6b6f746c696e782d636f726f7574696e65732d636f7265_knbridge828 + 188
at 13 libdispatch.dylib 0x000000010a9bdd10 _dispatch_call_block_and_release + 32
at 14 libdispatch.dylib 0x000000010a9bf18c _dispatch_client_callout + 20
at 15 libdispatch.dylib 0x000000010a9cdd14 _dispatch_main_queue_callback_4CF + 996
at 16 CoreFoundation 0x000000018d38f6b0 AF42303F-57B6-3C11-8F18-8E80ABF7D886 + 710320
at 17 CoreFoundation 0x000000018d38a2c8 AF42303F-57B6-3C11-8F18-8E80ABF7D886 + 688840
at 18 CoreFoundation 0x000000018d3898f4 CFRunLoopRunSpecific + 480
at 19 GraphicsServices 0x00000001977a0604 GSEventRunModal + 164
at 20 UIKitCore 0x000000019155d358 UIApplicationMain + 1944
at 21 HueEssentials-dev 0x0000000104902414 main + 80
at 22 libdyld.dylib 0x000000018d2052dc 322C4E05-D0CF-33F5-B996-CE5C67DF59B6 + 4828
One time I got this stack trace below from Ktor. In issue https://github.com/ktorio/ktor/issues/1540#issuecomment-570062372, @qwwdfsad left a comment that this issue will cause continuations to resume twice (unexpected). Maybe that explains this as well?
kotlin.IllegalStateException: No more continuations to resume
at 0 common 0x000000010735b4e0 kfun:kotlin.Throwable.<init>(kotlin.String?)kotlin.Throwable + 92
at 1 common 0x0000000107354608 kfun:kotlin.Exception.<init>(kotlin.String?)kotlin.Exception + 88
at 2 common 0x0000000107354044 kfun:kotlin.RuntimeException.<init>(kotlin.String?)kotlin.RuntimeException + 88
at 3 common 0x0000000107354858 kfun:kotlin.IllegalStateException.<init>(kotlin.String?)kotlin.IllegalStateException + 88
at 4 common 0x00000001075cc794 kfun:io.ktor.util.pipeline.SuspendFunctionGun.resumeRootWith#internal + 1408
at 5 common 0x00000001075cc03c kfun:io.ktor.util.pipeline.SuspendFunctionGun.loop#internal + 1188
at 6 common 0x00000001075cb71c kfun:io.ktor.util.pipeline.SuspendFunctionGun.proceed#internal + 352
at 7 common 0x00000001075cbad8 kfun:io.ktor.util.pipeline.SuspendFunctionGun.execute#internal + 412
at 8 common 0x00000001075c5328 kfun:io.ktor.util.pipeline.Pipeline.execute(TContext;TSubject)TSubject + 304
at 9 common 0x0000000107605f34 kfun:io.ktor.client.HttpClient.$executeCOROUTINE$1143.invokeSuspend(kotlin.Result<kotlin.Any?>)kotlin.Any? + 504
at 10 common 0x0000000107606200 kfun:io.ktor.client.HttpClient.execute(io.ktor.client.request.HttpRequestBuilder)io.ktor.client.call.HttpClientCall + 256
at 11 common 0x0000000107641568 kfun:io.ktor.client.statement.HttpStatement.$executeUnsafeCOROUTINE$1185.invokeSuspend(kotlin.Result<kotlin.Any?>)kotlin.Any? + 712
at 12 common 0x000000010764181c kfun:io.ktor.client.statement.HttpStatement.executeUnsafe$ktor-client-core()io.ktor.client.statement.HttpResponse + 212
at 13 common 0x0000000107b6dd24 kfun:com.superthomaslab.hueessentials.common.huesdk.bridge.hue.BridgeApi.$getDataStoreForceNetworkCOROUTINE$513.invokeSuspend(kotlin.Result<kotlin.Any?>)kotlin.Any? + 4260
at 14 common 0x0000000107b6eacc kfun:com.superthomaslab.hueessentials.common.huesdk.bridge.hue.BridgeApi.getDataStoreForceNetwork(kotlin.Boolean;kotlin.Boolean)io.ktor.utils.io.ByteReadChannel + 268
at 15 common 0x0000000107b6ec4c kfun:com.superthomaslab.hueessentials.common.huesdk.bridge.hue.BridgeApi.getDataStoreForceNetwork$default(kotlin.Boolean;kotlin.Boolean;kotlin.Int)io.ktor.utils.io.ByteReadChannel + 272
at 16 common 0x0000000107ac3c04 kfun:com.superthomaslab.hueessentials.common.huesdk.bridge.HeartbeatHelper.$createHeartbeat$lambda-0COROUTINE$336.invokeSuspend#internal + 4612
at 17 common 0x000000010737b238 kfun:kotlin.coroutines.native.internal.BaseContinuationImpl.resumeWith(kotlin.Result<kotlin.Any?>) + 524
at 18 common 0x00000001074cb660 kfun:kotlinx.coroutines.DispatchedTask.run() + 2284
at 19 common 0x0000000107505d10 kfun:kotlinx.coroutines.DarwinMainDispatcher.dispatch$lambda-0#internal + 112
at 20 common 0x00000001075060d0 kfun:kotlinx.coroutines.DarwinMainDispatcher.$dispatch$lambda-0$FUNCTION_REFERENCE$543.invoke#internal + 64
at 21 common 0x0000000107506130 kfun:kotlinx.coroutines.DarwinMainDispatcher.$dispatch$lambda-0$FUNCTION_REFERENCE$543.$<bridge-UNN>invoke()#internal + 64
at 22 common 0x00000001075071bc _6b6f746c696e782d636f726f7574696e65732d636f7265_knbridge828 + 188
at 23 libdispatch.dylib 0x000000010a9bdd10 _dispatch_call_block_and_release + 32
at 24 libdispatch.dylib 0x000000010a9bf18c _dispatch_client_callout + 20
at 25 libdispatch.dylib 0x000000010a9cdd14 _dispatch_main_queue_callback_4CF + 996
at 26 CoreFoundation 0x000000018d38f6b0 AF42303F-57B6-3C11-8F18-8E80ABF7D886 + 710320
at 27 CoreFoundation 0x000000018d38a2c8 AF42303F-57B6-3C11-8F18-8E80ABF7D886 + 688840
at 28 CoreFoundation 0x000000018d3898f4 CFRunLoopRunSpecific + 480
at 29 GraphicsServices 0x00000001977a0604 GSEventRunModal + 164
Furthermore, some logs I added show there are multiple network exceptions from Ktor before this crash occurs (kotlinx.coroutines.CancellationException: Socket timeout has been expired). That means the behaviour in my app is the same as this issue:
But when (performApiCall called from iOS, and) someApi.someMethod() throws some exception, then below crash happens:
Is there anything I can do to help? Users of my app are experiencing crashes due to this issue and I would really like to find a solution if that is possible.
It seems to be ktor-specific. I cannot figure out how to reproduce it in isolation.
This was happening to me when I was passing a massive string into the builder. Unsure if that helps.
Looks like this issue is fixed with Kotlin Coroutines 1.3.7-native-mt-1.4-M2 and Ktor 1.3.2-1.4-M2.
Closing as fixed
@qwwdfsad Getting the same crash with ktor 1.4.1 and coroutines 1.3.9-native-mt-2. How can we fix it?
Got the same error as well when implementing a suspending function in iOS code (KotlinSuspendFunction1) when calling the completion handler.
However, looking at the source code, CoroutineDispatcher.kt, line 103 (macosx64):
@InternalCoroutinesApi
public override fun releaseInterceptedContinuation(continuation: Continuation<*>) {
(continuation as DispatchedContinuation<*>).reusableCancellableContinuation?.detachChild()
}
Why not make this cast optional? Seems a bit dangerous to perform a forced downcast like that?
This cast cannot be made optional because it is supposed to always succeed.
When releaseInterceptedContinuation is invoked on the dispatcher that is different from the one that intercepted it, it only can indicate that some internal invariant is broken. It's better to fail fast in such situations instead of silently ignoring it (=> being silently buggy and inconsistent).
If the issue still persist with 1.3.9-native-mt-2, please create a separate issue with a reproducing project/test
1.4.2 or 1.4.3, but the issue went away when downgrading to 1.4.1 (all versions use coroutines 1.3.9-native-mt-2):CI run with 1.4.1: https://github.com/floscher/ktor-ClassCastException/runs/1590236500?check_suite_focus=true#step:4:14045
CI run with 1.4.2: https://github.com/floscher/ktor-ClassCastException/runs/1590216930?check_suite_focus=true#step:4:10133
CI run with 1.4.3: https://github.com/floscher/ktor-ClassCastException/runs/1589576823?check_suite_focus=true#step:4:10133
It occurs when writing more than ~4090 Bytes in call.respondTextWriter().
Most helpful comment
@qwwdfsad Getting the same crash with ktor 1.4.1 and coroutines 1.3.9-native-mt-2. How can we fix it?