Skip to content

flatMapLatest + combine + first leads to execution while cancelled #4034

Open
@ansman

Description

@ansman

Describe the bug

Firstly, it's possible this is expected behavior but it certainly doesn't seem that way.

We have a flow that we collect using first(). This flow is a combination of multiple upstream flows but they all emit their items synchronously. The downstream flow limits the number of emissions to a single element then uses awaitCompletion() to avoid terminating the flow. This is the flow we call first() on.

Under some circumstances, we are seeing the first() call resuming after the scope has been cancelled which is causing a crash for us.

If either the flatMapLatest or combine is removed, the code behaves as expected, although first() never resumes.

I know there are no real guarantees that code won't be running while canceled. But there are few things that makes me think that this doesn't apply in this case:

  • There is no non-cooperative suspension as far as I know.
  • Only a single thread is involved.

Provide a Reproducer
This reproduces it on an Android device, but it's possible it can reproed on the JVM too.

// This must be run on the main thread
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
println("Before launch")
scope.launch {
    flowOf(listOf(1, 2, 3))
        .flatMapLatest { numbers ->
            combine(numbers.map { flowOf(it) }) { it.sum() }
        }
        .onEach { println("Got item") }
        .first()
    println("After first, scope is active: ${scope.isActive}")
}
println("After launch")
scope.cancel()

I expect this to print:

Before launch
Got item
After first, scope is active: true
After launch

Instead I'm seeing this:

Before launch
Got item
After launch
After first, scope is active: false

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions