Android kotlin coroutine: await might silently drop exceptions

24
September 18, 2019, at 10:00 AM

While reading https://developer.android.com/kotlin/coroutines I stumbled upon the following warning:

Warning: launch and async handle exceptions differently. Since async expects an eventual call to await at some point, it holds exceptions and rethrows them as part of the await call. This means if you use await to start a new coroutine from a regular function, you might silently drop an exception. These dropped exceptions won't appear in your crash metrics or be noted in logcat.

However I'm not able to find any example of this silent-dropping behavior while browsing https://kotlinlang.org/docs/reference/coroutines/exception-handling.html or any other resources returned by https://www.google.com/search?q=kotlin+await+exception+handling - on the contrary, all resources indicate that exception thrown in an async/await block will cause a failure in the whole coroutine scope which is correct and expected.

I'm afraid I'm missing something here, can you provide an example where this silent exception dropping occurs which cannot be noted in logcat?

Answer 1

Exceptions from launch are thrown "instantly" into exception handler, while those from async will be thrown the moment you call await.

Sample code:

import kotlinx.coroutines.*
fun main(args: Array<String>) = runBlocking{
    println("main start")
    val l = GlobalScope.launch{ justThrow("launch") }
    val a = GlobalScope.async { justThrow("async") }
    delay(500)
    // a.await()
    println("main finished")
}
suspend fun justThrow(who : String){
    println("starting $who")
    delay(100)
    throw Exception("Test exception from $who")
}

Output:

main start
starting launch
starting async
Exception in thread "DefaultDispatcher-worker-2 @coroutine#2" java.lang.Exception: Test exception from launch
    at FileKt.justThrow(File.kt:15)
    (... entire stack here )
main finished

You can see launch throwing exception in worker thread but there's nothing from async, even though it executed the same function that must fail.

For next run modify the code by removing the launch for clarity and uncommenting a.await():

fun main(args: Array<String>) = runBlocking{
    println("main start")
    val a = GlobalScope.async { justThrow("async") }
    delay(500)
    a.await()
    println("main finished")
}

Output:

main start
starting async
Exception in thread "main" java.lang.Exception: Test exception from async
 at FileKt.justThrow (File.kt:15)
 (... entire stack here )

Exception is held instead of crashing in worker thread and is instead re-thrown the moment await() is called which causes the app to crash. You can notice it happened on main thread and there was no "main finished" print because of that.

READ ALSO
I opened android project but project can get SDK-tools

I opened android project but project can get SDK-tools

In MainAcitivity i am using ToolssystemBarLolipop() it is function from Tools

26
How to reduce video size with java/kotlin on Android?

How to reduce video size with java/kotlin on Android?

I want reduce the video size at Android Studio and for upload to PlayStore needs to be compatible for 64 bits arquitecture, I tried before with ffmpeg and it compress mp4 succefully but take longer time and this solution with 3gp not include the audioTheres...

56
Google sheets to salesforce

Google sheets to salesforce

Im trying to connect data in google sheet to salesforce

17
How to retrieve data from my java code to html?

How to retrieve data from my java code to html?

I am working on a small webpage projectI wrote my functions code with java, and now I am having problems to display the data I got to HTML to display it in a webpage

43