Kotlin/kotlinx.coroutines

incorrect Dispatchers.Main.immediate behavior

VladislavSumin opened this issue · 2 comments

Run this code:

        // main thread here.
        println("1")
        val scope1 = CoroutineScope(Dispatchers.Main.immediate)
        scope1.launch {
            println("2")
            val scope2 = CoroutineScope(Dispatchers.Main.immediate)
            scope2.launch {
                println("3")
            }
            println("4")
        }
        println("5")

I expect the output to be 1 2 3 4 5 but in reality the output will be 1 2 4 3 5.

The documentation for Dispatchers.Main.immediate does not warn about such behavior, so I am inclined to consider this behavior incorrect.

This example may seem bad, but in real code we would not expect the behavior of a function called on mainThread to be different depending on whether it is called inside a coroutine:

fun sample() {
    val scope2 = CoroutineScope(Dispatchers.Main.immediate)
    scope2.launch {
        println("3")
    }
    println("4")
}

I expect the output to be 1 2 3 4 5 but in reality the output will be 1 2 4 3 5.

This behaviour is in line with the immediate dispatcher contract from its documentation

In particular:

Immediate dispatcher is safe from stack overflows and in case of nested invocations forms event-loop similar to Dispatchers.Unconfined. The event loop is an advanced topic and its implications can be found in Dispatchers.Unconfined documentation.

Event loop documentation explicitly states that this behaviour is allowed.

Implementation-wise, this is a necessary step to prevent potential stackoverflows

Thank you for your answer, I agree that the documentation on the site actually says this.
Of course, this still seems like dangerous behavior since all your non-suspend functions in this way may depend on the location of the call, but if it is in the documentation and there are good reasons for this, then the bug can be closed. Thanks again for the quick response