Reputation: 60081
When I have
@Test
fun test() {
val handler = CoroutineExceptionHandler { _, exception ->
println("CoroutineExceptionHandler got $exception")
}
GlobalScope.launch(handler) {
throw IllegalAccessException("Just testing")
}
Thread.sleep(300)
}
It works fine printing
CoroutineExceptionHandler got java.lang.IllegalAccessException: Just testing
Process finished with exit code 0
Even if I replace GlobalScope
with MainScope()
, all still work fine.
However, if I use runBlocking
as below.,
@Test
fun test() {
val handler = CoroutineExceptionHandler { _, exception ->
println("CoroutineExceptionHandler got $exception")
}
runBlocking(handler) {
throw IllegalAccessException("Just testing")
}
Thread.sleep(300)
}
It crashes
java.lang.IllegalAccessException: Just testing
at com.example.coroutinerevise.CoroutineExperiment$test$1.invokeSuspend(CoroutineExperiment.kt:32)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:274)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:84)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at com.example.coroutinerevise.CoroutineExperiment.test(CoroutineExperiment.kt:31)
Why can't runBlocking have the given CoroutineExceptionHandler
triggered?
Upvotes: 5
Views: 2093
Reputation: 1724
it's not supported as per
https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/exception-handling.md#cancellation-and-exceptions
If a coroutine encounters an exception other than CancellationException, it cancels its parent with that exception. This behaviour cannot be overridden and is used to provide stable coroutines hierarchies for structured concurrency. CoroutineExceptionHandler implementation is not used for child coroutines.
And runBlocking creates a child coroutine
https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/run-blocking.html
Runs a new coroutine and blocks the current thread interruptibly until its completion.
Something like this will work, but it's kind of ugly
@Test
fun test() {
val handler = CoroutineExceptionHandler { _, exception ->
println("CoroutineExceptionHandler got $exception")
}
try{
runBlocking {
throw InterruptedException("Just testing")
}
} catch(e:Exception){
handler.handleException(GlobalScope.coroutineContext,e)
}
Thread.sleep(300)
}
Upvotes: 2