If change the dispatcher of the coroutine, the stack trace will be cropped
See original GitHub issueThere is a trivial case with nested calls to suspend functions. In the last of the calls, an exception is thrown, which is caught only in the start function, which launched this entire chain of suspend function calls, and the exception is sent to the log. It is argued that the stack trace in the log should be complete, since Stack trace recovery was released in 1.1 https://github.com/Kotlin/kotlinx.coroutines/issues/74 And it really seems to work, but only if you do not change the dispatcher in intermediate calls. But if you change it, then the stack stack turns out to be cut off.
Dispatcher change example:
val logger: Logger = LoggerFactory.getLogger("Main")
fun main() {
runBlocking {
try {
callThrowableSuspendFun()
} catch (ex: Exception) {
logger.error("Error while execute", ex)
}
}
}
suspend fun changeContextAndThrow(): String {
logger.info("Call function changeContextAndThrow")
return withContext(Dispatchers.IO) {
throw IllegalArgumentException("Throw from changeContextAndThrow")
}
}
suspend fun callThrowableSuspendFun(): String {
logger.info("Call function callThrowableSuspendFun")
return changeContextAndThrow()
}
Log:
83 [main] INFO Main - Call function callThrowableSuspendFun
83 [main] INFO Main - Call function changeContextAndThrow
98 [main] ERROR Main - Error while execute
java.lang.IllegalArgumentException: Throw from changeContextAndThrow
at MainKt$changeContextAndThrow$2.invokeSuspend(Main.kt:30)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:594)
at kotlinx.coroutines.scheduling.CoroutineScheduler.access$runSafely(CoroutineScheduler.kt:60)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:740)
An example without changing the dispatcher:
val logger: Logger = LoggerFactory.getLogger("Main")
fun main() {
runBlocking {
try {
callThrowableSuspendFun()
} catch (ex: Exception) {
logger.error("Error while execute", ex)
}
}
}
suspend fun changeContextAndThrow(): String {
logger.info("Call function changeContextAndThrow")
return coroutineScope {
throw IllegalArgumentException("Throw from changeContextAndThrow")
}
}
suspend fun callThrowableSuspendFun(): String {
logger.info("Call function callThrowableSuspendFun")
return changeContextAndThrow()
}
Log:
132 [main] INFO Main - Call function callThrowableSuspendFun
132 [main] INFO Main - Call function changeContextAndThrow
156 [main] ERROR Main - Error while execute
java.lang.IllegalArgumentException: Throw from changeContextAndThrow
at MainKt$changeContextAndThrow$2.invokeSuspend(Main.kt:30)
at MainKt$changeContextAndThrow$2.invoke(Main.kt)
at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:91)
at kotlinx.coroutines.CoroutineScopeKt.coroutineScope(CoroutineScope.kt:180)
at MainKt.changeContextAndThrow(Main.kt:29)
at MainKt.callThrowableSuspendFun(Main.kt:36)
at MainKt$main$1.invokeSuspend(Main.kt:20)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:270)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:79)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:54)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:36)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at MainKt.main(Main.kt:18)
at MainKt.main(Main.kt)
Issue Analytics
- State:
- Created 4 years ago
- Comments:8 (3 by maintainers)
Top Results From Across the Web
Kotlin Coroutines Dispatchers.IO is not creating expected ...
In each loop iteration, I'm creating a coroutine with Dispatchers.IO, But when I see the output, it is not created 1_000_000 coroutines, and...
Read more >Android Kotlin Coroutine Best Practices | by Ken Yee - Medium
The main dispatcher (if you don't specify anything to run on) is the UI one; you should only change UI elements in this...
Read more >Coroutine Exception Handling & Observability with Firebase
The default behavior to handle exceptions is simply to print the stack-trace but followed by the application crashing. So if you want to...
Read more >Coroutine context and dispatchers - Kotlin
The coroutine dispatcher can confine coroutine execution to a specific thread, dispatch it to a thread pool, or let it run unconfined.
Read more >Forget RxJava: Kotlin Coroutines are all you need. Part 1/2
Now a stack-trace comes from your crash reporting tool: ... What if Kotlin Coroutines can make our life better?
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
No, for the same reasons as it cannot be done with regular threads and context switches.
Quoting already mentioned documentation:
I wrote a workaround like this: