question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Exception thrown by async is not caught when parent job is cancelled.

See original GitHub issue

Sample code for the scenario.


import kotlinx.coroutines.*
import java.io.IOException
import java.lang.Exception

val contextJob = Job()

fun main() {
    GlobalScope.launch(contextJob) {
        try {
            apiRequest().await()
        } catch(e: Exception) {
            // Try to handle the exception gracefully
            println("Exception caught")
        }
    }.apply {
        // But parent job is canceled after a while
        Thread.sleep(300)
        contextJob.cancel()
    }

    Thread.sleep(3000L)
}

fun apiRequest() = GlobalScope.async(Dispatchers.IO) {
        // Do some network request
        Thread.sleep(1000)
        // An IOException is thrown
        throw IOException()
        "API Result"
    }

We have a contextJob in activity as the parent job of all coroutines which is cancelled in onDestroy(), as recommended in official guide.

The problem is that when the contextJob is cancelled while the async job is executing, the exception thrown by async will not be caught by the try…catch… block , and thus crashes our app.

I’m aware that CoroutineExceptionHandler can catch the exception, but then it brings a huge mental load during development. I would rather to not use contextJob at all.

When is the recommended way of dealing with this situation?

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:4
  • Comments:11 (2 by maintainers)

github_iconTop GitHub Comments

4reactions
qwwdfsadcommented, Dec 6, 2018

Then recommended solution is to wrap them into coroutineScope {} or supervisorScope {}`. We probably should update documentation in that place.

E.g.

suspend fun concurrentNetworkRequests() = coroutineScope {
  val first = firstRequest()
  val second = secondRequest()
  combineResults(first.await(), second.await())
}
0reactions
yihuaqicommented, Jan 4, 2019

@yihuaqi I have an exact same issue how do u solve that problem ?

We use add an CoroutineExceptionHandler for every coroutine we start to avoid crash for now.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Exceptions in coroutines. Cancellation and Exceptions in…
When a coroutine fails with an exception, it will propagate said exception up to its parent! Then, the parent will 1) cancel the...
Read more >
Avoid cancelling of parent job on exception on child coroutine
I've tried using a CoroutineExceptionHandler . It catches exception but cancels the Job too. Which in result cancels all other coroutines. What ...
Read more >
Coroutine exceptions handling | Kotlin
If a coroutine encounters an exception other than CancellationException , it cancels its parent with that exception.
Read more >
Things you should know about Coroutines. Part 4: Exception ...
The parent propagates the exception up to its parent or throws the ... Both exception propagation and cancellation work the same way.
Read more >
Structured concurrency explained - Part 2: Exceptions and ...
It all starts with the fetchFromRemote() throwing an exception, causing the Producer coroutine to fail. · The parent job notices the failure of...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found