/KotlinExceptions

An example of how Kotlin handles uncaught exceptions in Android.

Primary LanguageKotlinMIT LicenseMIT

KotlinExceptions

An example of a bug in how Kotlin handles uncaught exceptions in Android.

Reproduction:

This app has two buttons. A button that will correctly log an exception to the logcat, and a button that won't.

The button that logs the exception has its own CoroutineExceptionHandler that simply rethrows any exception that it encounters, allowing the system to pick it up.

The other button does not log the exception. It will instead call the Thread's default uncaught exception handler, which for Android is called the KillApplicationHandler which immediately kills the application.

Explanation

Android has an odd way of making sure uncaught exceptions are logged. It has a concept of a "Uncaught Exception PreHandler" which is called before the default uncaught exception handler when the system is handling an uncaught exception. This has the side-effect of making it so that calling the uncaught exception handler directly won't invoke the pre-handler. The relevant code for this can be found in Thread. Relevant methods in that class are #getDefaultUncaughtExceptionHandler, #getUncaughtExceptionPreHandler and #dispatchUncaughtException The actual handlers themselves are located in a class called RuntimeInit, with the pre-handler being RuntimeInit$LoggingHandler and the normal handler being RuntimeInit$KillApplicationHandler

Solution:

Admittedly, rethrowing the exception is probably not a good idea. I don't claim to understand the logistics behind that, nor the performance penalties that might be incurred by doing it that way. However, for the short term, it does work. This has an unfortunate side-effect of including some coroutine specific code in the trace, but that isn't an issue in my opinion.

It is also possible to simply log the exception manually in a CoroutineExceptionHandler, mimicking what Android's uncaught exception pre-handler does for you.