Kotlin / kotlinx.coroutines

Library support for Kotlin coroutines
Apache License 2.0
12.94k stars 1.84k forks source link

`withContext` may execute code in the wrong context if the `coroutineContext` misleads it #4193

Closed dkhalanskyjb closed 1 month ago

dkhalanskyjb commented 1 month ago

Describe the bug

Encountered by the IntelliJ team. withContext looks at the current coroutine context and decides whether it should perform a dispatch. However, the current coroutine context does not always correctly reflect which thread the coroutine executes on. So, withContext may believe that it doesn't have to dispatch when it actually does.

Provide a Reproducer

import kotlinx.coroutines.*

fun main() {
    runBlocking {
        launch(Dispatchers.Default, start = CoroutineStart.UNDISPATCHED) {
            // yield() // one way to work around this
            withContext(Dispatchers.Default) {
                // yield() // another way to work around this
                println("Current thread is ${Thread.currentThread()}")
            }
        }
    }
}

(https://pl.kotl.in/POeZD53Uw) prints

Current thread is Thread[main @coroutine#2,5,main]

which is not a Dispatchers.Default thread.

dkhalanskyjb commented 1 month ago

A slightly different case of the same:

import kotlinx.coroutines.withContext
import kotlinx.coroutines.Dispatchers
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.*

suspend fun x(input: Unit): Int {
    withContext(Dispatchers.Default) {
        println("Current thread is ${Thread.currentThread()}")
    }
    return 5
}

object MyContinuation: Continuation<Int> {
    override val context: CoroutineContext = Dispatchers.Default
    override fun resumeWith(result: Result<Int>) {
        println(result)
    }
}

fun main() {
    ::x.createCoroutineUnintercepted(Unit, MyContinuation).resumeWith(Result.success(Unit))
    Thread.sleep(200)
}

https://pl.kotl.in/iIvxOM2pT

Current thread is Thread[main,5,main]
Success(5)
qwwdfsad commented 1 month ago

See also https://github.com/Kotlin/kotlinx.coroutines/issues/286

dovchinnikov commented 1 month ago

I propose to proceed in #286