Skip to content

Missing updateThreadContext call when emit resumes #4590

@cdli-corp

Description

@cdli-corp

Hi Kotlin team,

IIUC, each coroutine should have a dedicated CopyableThreadContextElement, and use this element to call updateThreadContext and restoreThreadContext at the beginning and end of each sub-routine, respectively. However, we found that is not always the case, and here is an example: https://pl.kotl.in/USpmRjCNL.

The following details my observation of the code's execution:

val flow = 
    flow {
        // 1. Here updateThreadContext is called on 
        //    TestElement("flowOn")'s child (the distinction is "flowOn" v.s. "collect", where child is immaterial, 
        //    so will skip mentioning child in the following explanation)
        log("before emit")
        // 2. We call the block in collect below, and suspend
        emit(1)
        // 4. As we reach here, TestElement("flowOn").updateThreadContext is not called
        //    although the current context is (has, but use "is" for the simplicity of explanation) TestElement("flowOn")
        log("after emit")
    }
    .flowOn(TestElement("flowOn", null))

launch(TestElement("collect", null)) {
    flow.collect {
        reached.set(true)
        log("collect about to lock")
        mutex.lock()
        // 3. When resuming, updateThreadContext is called on TestElement("collect")
        log("collect resumed")
    }
}

Here is the highlighted output to show so:

[13] updateThreadContext: TestElement(name=child[0], parent=TestElement(name=collect, parent=null))
[13] collect resumed
// <- no updateThreadContext for TestElement("flowOn")
[13] after emit
[13] restoreThreadContext: TestElement(name=child[0], parent=TestElement(name=collect, parent=null))

For context we have a ThreadLocal-based tracing system, which supports coroutine tracing with the help of CopyableThreadContextElement, and we have clients broken by this because the correct trace is not restored (for the missing updateThreadContext call). So post the finding here and see if we can get this fixed, thanks!

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