Skip to content

Exceptions thrown by CoroutineExceptionHandler must be caught by handleCoroutineException() #562

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
abusalimov opened this issue Sep 14, 2018 · 1 comment

Comments

@abusalimov
Copy link

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?

@elizarov
Copy link
Contributor

elizarov commented Sep 15, 2018

I don't have a good answer. Coroutine exception handler is the last resort. If it throws exception then what else we can do with it? The only suggestion I can make is that we can have a separate try-catch for a user-defined exception handler (like in your case) and if that crashed, then we can use a default exception handler as a fall-back.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants