Why does the second coroutine gets cancelled although I have used SupervisorJob()? The code targets the JVM.
fun main() {
val handler =
CoroutineExceptionHandler { _, _ -> println("handling the error") }
CoroutineScope(SupervisorJob() + handler).launch {
println(Thread.currentThread().name)
launch {
println(Thread.currentThread().name)
println("...")
delay(500)
throw RuntimeException("failing first coroutine")
}
launch {
println(Thread.currentThread().name)
println("fetching some data over the network")
delay(1000)
println("Done")
}
}
Thread.sleep(2000)
}
From the documentation:
Children of a supervisor job can fail independently of each other.
The issue here is that the two inner coroutines are not children of the supervisor job, they are grand-children. The only child of the supervisor job is the coroutine you directly launch in it. Let's call it coroutine A:
CoroutineScope(SupervisorJob() + handler).launch {
// child of supervisor job
}
Then this child's scope is used to launch two other coroutines (B and C). The supervisor job does not propagate to child coroutines. If it would, a nested coroutine's behavior would become unpredictable. That is why failing B fails A and that, in turn cancels all other children of A, which is C.
For your code to run as expected, you need to make both coroutines B and C children of the supervisor job. That could look like this:
val scope = CoroutineScope(SupervisorJob() + handler)
println(Thread.currentThread().name)
scope.launch {
println(Thread.currentThread().name)
println("...")
delay(500)
throw RuntimeException("failing first coroutine")
}
scope.launch {
println(Thread.currentThread().name)
println("fetching some data over the network")
delay(1000)
println("Done")
}
Thread.sleep(2000)
By removing A and launching B and C directly in the scope with the supervisor job, when coroutine B fails, C will not automatically be cancelled.