Closed
Description
Currently exceptions thrown by CoroutineExceptionHandler
are retrown from the handleCoroutineException()
, possibly wrapped into a RuntimeException
:
public actual fun handleCoroutineException(context: CoroutineContext, exception: Throwable) {
try {
/* invoke CoroutineExceptionHandler.handleException()
and currentThread.uncaughtExceptionHandler.uncaughtException() */
} catch (handlerException: Throwable) {
// simply rethrow if handler threw the original exception
if (handlerException === exception) throw exception
// handler itself crashed for some other reason -- that is bad -- keep both
throw RuntimeException("Exception while trying to handle coroutine exception", exception).apply {
addSuppressed(handlerException)
}
}
}
It is unclear now what consequences this behavior can lead to, but the comment inside the catch { ... }
clause, telling that -- that is bad --
is probably right.
It feels that handleCoroutineException()
must guarantee not to throw, or at least make sure the exception is delivered to a proper piece of code that is expecting it.
Some background:
val exceptionHandler = context[CoroutineExceptionHandler] ?: CoroutineExceptionHandler { coroutineContext, throwable ->
LOG.error("Unhandled exception from $coroutineContext", throwable)
}
This seemingly harmless piece of logic can actually throw an AssertionError
in IDEA when running in unit testing mode. What is the right way of dealing with it?
Metadata
Metadata
Assignees
Labels
No labels