Open
Description
https://betterprogramming.pub/the-silent-killer-thats-crashing-your-coroutines-9171d1e8f79b raises a good point: CancellationException
should indicate that the coroutine in which it is raised is cancelled, but it's not always actually the case:
fun testFoo() {
val scope = CoroutineScope(Dispatchers.IO)
val f = scope.async {
delay(1000)
}
scope.cancel()
var result = false
runBlocking {
launch {
f.await() // throws CancellationException, silently stopping the `launch` coroutine
result = true
}.join()
}
check(result) { "issue" }
}
Here, the programmer didn't make the mistake of catching a CancellationException
and rethrowing it somewhere else, but still, the CancellationException
leaked from a different scope.