I am running a coroutine in a SupervisorJob with a try/catch block surrounding only the await calls. The exception from the async block gets caught by the try/catch, but it still gets propagated and the app crashes.
This is what I have:
CoroutineScope(Dispatchers.IO + SupervisorJob()).launch {
val a = async {
delay(500)
throw Exception("excep a")
2
}
val b = async {
delay(500)
3
}
try {
println(a.await() + b.await())
} catch (e: Exception) {
println("exception: ${e.message}")
}
}
This is what I get (note that "excep a" gets caught):
exception: excep a
Exception in thread "DefaultDispatcher-worker-3 @coroutine#1" java.lang.Exception: excep a
at com.example.app.AuthTest$co2$1$a$1.invokeSuspend(AuthTest.kt:314)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:571)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:678)
at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:665)
The exception handling mechanism of supervisorJob and Job is not the same. For supervisory tasks, the transmission of exceptions can only be from the parent scope to the child scope, and the propagation direction of the exception is one-way. Therefore, it is necessary to handle exceptions by itself for monitoring the scope of opening the coroutine.
CoroutineScope(Dispatchers.IO + SupervisorJob()).launch(CoroutineExceptionHandler { _, throwable ->
println("$throwable")
}) {
val a = async {
delay(500)
throw Exception("excep a")
2
}
val b = async {
delay(500)
3
}
println(a.await() + b.await())
}
This exception will be handled in the top-level Job
SupervisorJob has launch as Top coroutine and both async/await are nested coroutines.
Nested async/await always propagated up via Job hierarchy even if you use try/catch.
launch as Top coroutine require CoroutineExceptionHandler.
Alternatively you can:
async and try/catch in supervisorScopeasync and try/catch in coroutineScope inside try/catch. But in this case second async will be cancelled after exception is thrownIf you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With