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`…)launch
? (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 PMCoroutineExceptionHandler
of that parent is usedcoroutinesScope
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 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)
}
fun launch_handleExceptionUsingCoroutineExceptionHandler(): Unit {
CoroutineScope(Dispatchers.Default).launch(xHandlerParent) {
launch(xHandlerLeaf) {
delay(1000)
throw Exception("Some Exception 1")
}
}
Thread.sleep(2000)
}