0

I’ve read in multiple places that async can swallow exceptions if we don’t call await, but as far as I can see, it almost always throws them regardless of whether await is used or not.

For example, here, I’d assume it’s too late to catch, since it has already propagated, so it crashes

lifecycleScope.launch {
    val job = async {
        throw Exception()
    }

    try {
        job.await()
    } catch (e: Exception) {
        println("caught")
    }
}

But in a similar scenario, I would assume it should propagate to the outer async, yet the catch block runs and there’s no crash:

val scope = CoroutineScope(Job())
scope.async {
    val job = async {
        throw Exception()
    }

    try {
        job.await()
    } catch (e: Exception) {
        println("caught")
    }
} 

But here, async is actually able to store it and catch it later:

val job = lifecycleScope.async {
    launch {
        throw Exception()
    }
}

runBlocking {
    try {
        job.await()
    } catch (e: Exception) {
        println("caught")
    }
}

Here, I would assume the async and launch blocks run in parallel, and the try-catch should be able to observe and catch the exception, but it crashes:

runBlocking {
    async {
        val job = async {
            throw Exception()
        }
        launch {
            try {
                job.await()
            } catch (e: Exception) {
                println("caught")
            }
        }
    }
}

Yet, if I move out the await from launch, it works again:

lifecycleScope.async {
    val job = async {
        throw Exception()
    }

    try {
        job.await()
    } catch (e: Exception) {
        println("caught")
    }
}

Sometimes the catch block actually runs, but it still crashes, regardless of whether I break structured concurrency or not:

val scope = CoroutineScope(Job())
scope.async {
    val job = async {
        throw Exception()
    }

    try {
        job.await()
    } catch (e: Exception) {
        println("caught")
    }
}

I had an assumption that it depends on the runtime exception handler, based on this: https://stackoverflow.com/a/60078180/10698676, but most of the crashes above occur regardless of whether I’m running on Android or JVM.

My another assumtion was that maybe it depends on the thread, since sometimes exception just logged, so I assumed maybe it only crashes on Main thread, but not on IO/Default, but it didn't matter which Dispatcher I used, the results were the same.

I tried many other variation, but couldn't figure out the principle So how does this work? What am i missing ?

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.