Whenever an exception happens, it's redirected to the handleCoroutineException() function, which looks like this:
public fun handleCoroutineException(context: CoroutineContext, exception: Throwable) {
try {
context[CoroutineExceptionHandler]?.let {
it.handleException(context, exception)
return
}
if (exception is CancellationException) return
context[Job]?.cancel(exception)
handleCoroutineExceptionImpl(context, exception)
} catch (handlerException: Throwable) {
if (handlerException === exception) throw exception
throw RuntimeException(
"Exception while trying to handle coroutine exception",
exception).apply {
addSuppressedThrowable(handlerException)
}
}
}
Let's break down the different parts of this code and analyze what it does.