Skip to content

Clarifications on the documented behavior of supervisorScope W.R.T. its parent. #3725

Closed
@psteiger

Description

@psteiger

The KDoc for supervisorScope states that:

A failure of the scope itself (exception thrown in the block or external cancellation) fails the scope with all its children, but does not cancel parent job.

I might be missing something obvious, but how can an exception thrown at supervisorScope block not cancel the parent Job?

  1. If we throw inside supervisorScope block, this exception is rethrown, so it obviously cancels the parent:
fun main() = runBlocking<Unit> {
   coroutineContext.job.invokeOnCompletion { println("Parent job cancelling with $it") }
   supervisorScope {
       error("Some error")
   }
}

Output:

Parent job cancelling with java.lang.IllegalStateException: Some error
Exception in thread "main" java.lang.IllegalStateException: Some error
	at Main2Kt$main$1$2.invokeSuspend(Main2.kt:19)
	at Main2Kt$main$1$2.invoke(Main2.kt)
	at Main2Kt$main$1$2.invoke(Main2.kt)
	at kotlinx.coroutines.intrinsics.UndispatchedKt.startUndispatchedOrReturn(Undispatched.kt:89)
	at kotlinx.coroutines.SupervisorKt.supervisorScope(Supervisor.kt:61)
        ...
  1. If we cancel the supervisorScope job with an exception, it also fails the parent:
fun main() = runBlocking<Unit> {
    coroutineContext.job.invokeOnCompletion { println("Parent job cancelling with $it") }
    supervisorScope {
        cancel("Cancelling supervisor scope", IllegalStateException("Some error"))
    }
}

Output:

Parent job cancelling with java.util.concurrent.CancellationException: Cancelling supervisor scope
Exception in thread "main" java.util.concurrent.CancellationException: Cancelling supervisor scope
	at kotlinx.coroutines.ExceptionsKt.CancellationException(Exceptions.kt:22)
	at kotlinx.coroutines.CoroutineScopeKt.cancel(CoroutineScope.kt:295)
	...
Caused by: java.lang.IllegalStateException: Some error
	... 16 more
  1. The behavior outlined above is exactly the same with the coroutineScope builder.

So I'm wondering what the docs really mean. If documentation is indeed correct, is it possible to provide a small code example in the docs to exemplify the stated behavior (and how it differs from coroutineScope)?

Please note that this is not regarding SupervisorJob behavior regarding children cancellation and failure, which I think is clear. But the SupervisorJob behavior WRT its parent, and also specifically the behavior of the supervisorScope builder WRT exceptions thrown in the scope block (not on children coroutines).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions