streetsofboston
04/25/2019, 8:53 PMval xHandler = CoroutineExceptionHandler { c, e ->
println("Handled Crash in coroutine $c")
e.printStackTrace(System.out)
}
fun launch_handleExceptionInCoroutineExceptionHandler(): Unit = runBlocking(xHandler) {
launch(<http://Dispatchers.IO|Dispatchers.IO> + xHandler) {
delay(1000)
throw Exception("Some Exception 1")
}
delay(2000)
}
fun main() {
Thread.setDefaultUncaughtExceptionHandler { t, e ->
println("App Crash in thread $t")
e.printStackTrace(System.out)
}
launch_handleExceptionInCoroutineExceptionHandler()
}
The xHandler is never called.
The output is produced by the default-uncaught-exception-handler instead.
I expected the xHandler to be called.
If I provide another scope to the launch, eg GlobalScope.launch { ... } it works as expected and the xHandler is called.
Why is the xHandler not called when using the `runBlocking`’s scope?
(just to be sure, I provided the xHandler in 2 places, when calling runBlocking and when calling `launch`…)streetsofboston
04/26/2019, 2:30 PMlaunch? (cc @elizarov)elizarov
04/26/2019, 2:32 PMCoroutineExceptionHandler is only used for uncaught exceptions. If there is a parent that handles exception, then CoroutineExceptionHandler is not used at allstreetsofboston
04/26/2019, 2:40 PMThrowable thrown in a a launch bubbles all the way up to the top-most parent coroutine-scope that has an CoroutineExceptionHandler, ignoring any `CoroutineExceptionHandler`s in child-coroutinescopes. Is this correct?
But when calling runBlocking, its CoroutineScope does not seem to have a CoroutineExceptionHandler, because it the code-example, the ‘default-uncaught-exception-handler’ is invoked.elizarov
04/26/2019, 2:41 PMelizarov
04/26/2019, 2:41 PMCoroutineExceptionHandler of that parent is usedelizarov
04/26/2019, 2:43 PMcoroutinesScope and runBlocking don’t use CoroutineExceptionHandler at all! They simply throw the corresponding exception up the call stackstreetsofboston
04/26/2019, 2:44 PMtry { ... } catch(...) { ... } block in your launch.
For the runBlocking (and coroutineScope): Even if one of its child-coroutinescopes issues a launch with a context that does have a CoroutineExceptionHandler, they’ll throw it up the call-stack?elizarov
04/26/2019, 2:46 PMlaunch { try { ... } catch(...) { ... } }
2. Yes. So you can do
try { coroutineScope { ... } } catch(...) { ... }streetsofboston
04/26/2019, 2:46 PMstreetsofboston
04/26/2019, 4:33 PMxHandlerParent should handle it, not xParentLeaf as in the example below.
The thrown Exception is handled by `xHandlerLeaf`… Shouldn’t it be xHandlerParent?
fun launch_handleExceptionUsingCoroutineExceptionHandler(): Unit {
CoroutineScope(xHandlerParent).launch(xHandlerLeaf) {
delay(1000)
throw Exception("Some Exception 1")
}
Thread.sleep(2000)
}streetsofboston
04/29/2019, 4:23 PMfun launch_handleExceptionUsingCoroutineExceptionHandler(): Unit {
CoroutineScope(Dispatchers.Default).launch(xHandlerParent) {
launch(xHandlerLeaf) {
delay(1000)
throw Exception("Some Exception 1")
}
}
Thread.sleep(2000)
}