Skip to content

NonCancellable section can be cancelled when combined with another context #4300

@andrew-k-21-12

Description

@andrew-k-21-12

This can be my misunderstanding about how NonCancellable is expected to work, but it seems like a bug or some missing documentation note by default.

Used kotlinx-coroutines-core of version 1.9.0 in a JVM example project.

The code to reproduce:

fun main(): Unit = runBlocking {
    val job = launch {
        while (true) {
            println("Before NonCancellable section ${Thread.currentThread().name}")
            withContext(NonCancellable + Dispatchers.IO) {
                println("Inside NonCancellable section ${Thread.currentThread().name}")
            }
            println("After NonCancellable section ${Thread.currentThread().name}")
        }
    }
    delay(20)
    println("Trying to cancel the job ${Thread.currentThread().name}")
    job.cancelAndJoin()
    println("The job has been finished ${Thread.currentThread().name}")
}

The only call which checks for the cancellation inside the launch { ... } section is withContext(...) { ... }. Since the coroutine has been launched, I expected it to run in the cycle forever due to the NonCancellable context.

But it actually ends with the following logs:

Before NonCancellable section main
Inside NonCancellable section DefaultDispatcher-worker-1
Trying to cancel the job main
The job has been finished main

In other words, it gets cancelled anyway somewhere at the moment of exiting from the withContext section.

Changing the order of NonCancellable + Dispatchers.IO to Dispatchers.IO + NonCancellable doesn't update the result behavior anyhow.

Removing Dispatchers.IO or putting it as a nested call inside make the execution work as I expect it to:

withContext(NonCancellable) {
    withContext(Dispatchers.IO) {
        println("Inside NonCancellable section ${Thread.currentThread().name}")
    }
}

Is this cancelling behavior described above expected? Or do I miss some important rule to use NonCancellable?

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