I’m trying to grasp the coroutinescopes more and I’m having difficulties understanding some of the issues I’m encountering. An example of such is the withTimeout coroutine. I have the following example:
Link: Kotlin Playground: Edit, Run, Share Kotlin Code Online
import kotlin.system.exitProcess
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
// Expect a hard kill as the inner coroutine is taking much longer than the outer
suspend fun main() {
println("start")
coroutineScope {
withContext(Dispatchers.Default) {
withTimeout(5_000) {
val startTime = System.currentTimeMillis()
println("with 5sec timeout")
delay(3_000)
try {
withTimeout(10_000) {
println("with 3sec timeout")
delay(3_000)
println("passed 5sec timeout")
delay(3_000)
}
} catch (t: Throwable) {
println("caught ${t.message} after ${System.currentTimeMillis() - startTime}")
throw t
} finally {
println("Did finally after ${System.currentTimeMillis() - startTime}")
}
}
}
}
println("done")
exitProcess(0)
}
As shown we have a suspendable function and a coroutineScope is created. This has a withContext, currently with the Default dispatcher, I’ve also tried it without this dispatcher. Subsequently there’s a nested withTimeout.
What I would be expecting is that the outer timeout would throw a TimeoutCancellationException as the inner timeout is surpassing the threshold of the 5s of the outer. What you can however see happening is that the catch is catching the exception.
The questions/difficulties that I have:
- Is the nested timeout joining context causing the catch to trigger?
- What would be a solution where the nested timeout structure would work out as expected
- Any other suggestions are welcome
Of course the example here is a bit daft, but a scenario with a larger outer and lower inner timeouts would be more suitable. I find the behaviour strange and trying to understand what’s happening and I’m missing.