coroutineScope: cancels all its children when the parent is cancelled
coroutineScope creates a new Regular Job that but because it inherits from parent Job, if parent is cancelled it will cancel all its children and shut itself down.
Example code showing that children got cancelled when parent job got cancelled.
Code
package com.glassthought.sandbox
import com.glassthought.sandbox.util.out.impl.out
import gt.sandbox.util.output.Out
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlin.system.exitProcess
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
private suspend fun mainImpl(out: Out) {
coroutineScope {
out.info("In top level coroutineScope")
// Launch a job that we can cancel
val parentJob = launch {
foo("msg-1")
}
// Cancel the parent job after some delay
launch {
out.delayedActionWithMsg(
"going to cancel parentJob() of foo()",
{ parentJob.cancel() },
delayBeforeAction = 1100.milliseconds
)
}
}
}
private suspend fun foo(msg: String) {
out.actionWithMsg("functionThatStartsCoRoutineScope()", {
functionThatStartsCoRoutineScope(msg)
})
}
private suspend fun functionThatStartsCoRoutineScope(msg: String) {
coroutineScope {
out.info("This coroutineScope suspends the calling function.")
async {
out.delayNamed(3.seconds, "delayed([${msg}])")
}
async {
out.delayNamed(2.seconds, "delayed([${msg}])")
}
launch {
out.delayNamed(1.seconds, "delayed([${msg}])")
}
out.info("Just launched child coroutines")
}
}
fun main(): Unit = runBlocking {
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 3c067913265186682e70 \
&& 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: 13ms][🥇][①][coroutname:@coroutine#1][tname:main/tid:1] START - ON MAIN
[INFO][elapsed: 28ms][🥇][①][coroutname:@coroutine#1][tname:main/tid:1] In top level coroutineScope
[INFO][elapsed: 32ms][🥇][⓶][coroutname:@coroutine#2][tname:main/tid:1] [>] Starting action=[functionThatStartsCoRoutineScope()]
[INFO][elapsed: 32ms][🥇][⓶][coroutname:@coroutine#2][tname:main/tid:1] This coroutineScope suspends the calling function.
[INFO][elapsed: 33ms][🥇][⓶][coroutname:@coroutine#2][tname:main/tid:1] Just launched child coroutines
[INFO][elapsed: 34ms][🥇][⓷][coroutname:@coroutine#3][tname:main/tid:1] 1.1s delay, before_action=[going to cancel parentJob() of foo()]
[INFO][elapsed: 37ms][🥇][⓸][coroutname:@coroutine#4][tname:main/tid:1] Delaying for 3s what_for=[delayed([msg-1])]
[INFO][elapsed: 37ms][🥇][⓹][coroutname:@coroutine#5][tname:main/tid:1] Delaying for 2s what_for=[delayed([msg-1])]
[INFO][elapsed: 37ms][🥇][⓺][coroutname:@coroutine#6][tname:main/tid:1] Delaying for 1s what_for=[delayed([msg-1])]
[INFO][elapsed: 1039ms][🥇][⓺][coroutname:@coroutine#6][tname:main/tid:1] Done delaying for 1s what_for=[delayed([msg-1])]
[INFO][elapsed: 1136ms][🥇][⓷][coroutname:@coroutine#3][tname:main/tid:1] Done with=1.1s delay performing action=[going to cancel parentJob() of foo()]
[INFO][elapsed: 1138ms][🥇][⓷][coroutname:@coroutine#3][tname:main/tid:1] performed action=[going to cancel parentJob() of foo()]
[WARN][elapsed: 1186ms][🥇][⓸][coroutname:@coroutine#4][tname:main/tid:1] 🫡 I have caught [JobCancellationException/StandaloneCoroutine was cancelled], and rethrowing it 🫡
[WARN][elapsed: 1186ms][🥇][⓹][coroutname:@coroutine#5][tname:main/tid:1] 🫡 I have caught [JobCancellationException/StandaloneCoroutine was cancelled], and rethrowing it 🫡
[INFO][elapsed: 1187ms][🥇][⓶][coroutname:@coroutine#2][tname:main/tid:1] [<][🫡] Cancellation Exception - rethrowing.
[INFO][elapsed: 1187ms][🥇][①][coroutname:@coroutine#1][tname:main/tid:1] DONE - WITHOUT errors on MAIN
Backlinks