⚠️ does-not-cancel-parent-or-siblings-on-timeout ⚠️
When withTimeout
fails it will throw TimeoutCancellationException
which is a subtype of CancellationException, so it does NOT cancel parent or its siblings (even when we are running with Regular Job)
Example that illustrates that sibling is able to finish, AFTER a co-routine times out
Code
package com.glassthought.sandbox
import com.glassthought.sandbox.util.out.impl.out
import gt.sandbox.util.output.Out
import kotlinx.coroutines.*
import kotlin.system.exitProcess
import kotlin.time.Duration.Companion.seconds
private suspend fun mainImpl(out: Out) {
coroutineScope {
foo()
}
}
private suspend fun foo() {
val result = out.actionWithMsg("fooImpl", { fooImpl() })
out.info("Got result from fooImpl: [$result]")
}
private suspend fun fooImpl(): String {
return coroutineScope {
launch(CoroutineName("IWillTimeOut")) {
out.info("I am going to timeout!")
withTimeout(1.seconds) {
out.delayNamed(5.seconds, "delay(5.seconds) longer than surrounding withTimeout(1.seconds)")
}
}
val deferredResult = async(CoroutineName("IWillReturnResult")) {
out.delayNamed(3.seconds, "result")
"async-result"
}
deferredResult.await()
}
}
fun main(): Unit = runBlocking(CoroutineName("RunBlocking-At-Main")) {
out.info("START - ON MAIN")
try {
mainImpl(out)
} catch (e: Exception) {
out.error("back at MAIN got an exception! of type=[${e::class.simpleName}] with msg=[${e.message}] cause=[${e.cause}]. Exiting with error code 1")
exitProcess(1)
}
out.info("DONE - WITHOUT errors on MAIN")
}
Command to reproduce:
gt.sandbox.checkout.commit 547cdde62132766fd2fa \
&& cd "${GT_SANDBOX_REPO}" \
&& cmd.run.announce "./gradlew run --quiet"
Recorded output of command:
Picked up JAVA_TOOL_OPTIONS: -Dkotlinx.coroutines.debug
Picked up JAVA_TOOL_OPTIONS: -Dkotlinx.coroutines.debug
[INFO][elapsed: 14ms][🥇][①][coroutname:@RunBlocking-At-Main#1][tname:main/tid:1] START - ON MAIN
[INFO][elapsed: 31ms][🥇][①][coroutname:@RunBlocking-At-Main#1][tname:main/tid:1] [>] Starting action=[fooImpl]
[INFO][elapsed: 35ms][🥇][⓶][coroutname:@IWillTimeOut#2][tname:main/tid:1] I am going to timeout!
[INFO][elapsed: 39ms][🥇][⓶][coroutname:@IWillTimeOut#2][tname:main/tid:1] Delaying for 5s what_for=[delay(5.seconds) longer than surrounding withTimeout(1.seconds)]
[INFO][elapsed: 39ms][🥇][⓷][coroutname:@IWillReturnResult#3][tname:main/tid:1] Delaying for 3s what_for=[result]
[WARN][elapsed: 1086ms][🥇][⓶][coroutname:@IWillTimeOut#2][tname:main/tid:1] 🫡 I have caught [TimeoutCancellationException/Timed out waiting for 1000 ms], and rethrowing it 🫡
[INFO][elapsed: 3040ms][🥇][⓷][coroutname:@IWillReturnResult#3][tname:main/tid:1] Done delaying for 3s what_for=[result]
[INFO][elapsed: 3041ms][🥇][①][coroutname:@RunBlocking-At-Main#1][tname:main/tid:1] [<] Finished action=[fooImpl].
[INFO][elapsed: 3041ms][🥇][①][coroutname:@RunBlocking-At-Main#1][tname:main/tid:1] Got result from fooImpl: [async-result]
[INFO][elapsed: 3041ms][🥇][①][coroutname:@RunBlocking-At-Main#1][tname:main/tid:1] DONE - WITHOUT errors on MAIN
Backlinks