Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

withContext calls are not reflected in coroutine debug dumps #4299

Open
vsalavatov opened this issue Dec 16, 2024 · 2 comments
Open

withContext calls are not reflected in coroutine debug dumps #4299

vsalavatov opened this issue Dec 16, 2024 · 2 comments

Comments

@vsalavatov
Copy link

vsalavatov commented Dec 16, 2024

Reproducer:

@Test
fun testProbes() = runBlocking {
    val b1 = CompletableDeferred<Unit>()
    val b2 = CompletableDeferred<Unit>()
    println("runBlocking context: ${currentCoroutineContext()}")
    launch { // in the context of runBlocking
        withContext(Dispatchers.IO + CoroutineName("A")) {
            println("launched job context: ${currentCoroutineContext()}")
            b1.complete(Unit)
            b2.await()
        }
    }
    b1.await()
    println("debug probes")
    println(DebugProbes.dumpCoroutinesInfo())
}

Outputs:

runBlocking context: [CoroutineId(1), "coroutine#1":BlockingCoroutine{Active}@b665f0a, BlockingEventLoop@3c0fe39d]
launched job context: [CoroutineId(2), CoroutineName(A), "A#2":DispatchedCoroutine{Active}@2cd23013, Dispatchers.IO]
debug probes
[CoroutineInfo(state=RUNNING,context=[CoroutineId(1), "coroutine#1":BlockingCoroutine{Active}@b665f0a, BlockingEventLoop@3c0fe39d]), CoroutineInfo(state=SUSPENDED,context=[CoroutineId(2), "coroutine#2":StandaloneCoroutine{Active}@7ed255c1, BlockingEventLoop@3c0fe39d])]

Note that the debug info for the second coroutine does not show the effect of withContext switch.

This is likely because kotlinx.coroutines.debug.internal.DebugCoroutineInfoImpl has immutable context and it is not updated from the frame in updateState.

The issue occasionally shows up in problem investigations, wrong context in the debug probes causes confusion.

@vsalavatov vsalavatov added the bug label Dec 16, 2024
@qwwdfsad qwwdfsad added debug and removed bug labels Dec 16, 2024
@qwwdfsad
Copy link
Member

That's a long-standing debate (#3414 (comment)) about whether withContext is a new coroutine or not (and, for the change, coroutineScope) and is done on purpose in the current implementation. You can see that the actual contextual data is attached to the launched job context, including the name.

We can change that behaviour, but design help might be needed -- because scoped coroutines are filtered on purpose -- in the dumps, in the text output etc., and in other places they are, on purpose, a single coroutine with their outer scope (so it's actually walkable with coroutine debugger/stackframe walker etc.).

Maybe a special note in the text dump would do?

@vsalavatov
Copy link
Author

vsalavatov commented Dec 16, 2024

Hmm, it may be fun to see all context switches in the stacktraces.
Sketched this approach: https://gist.github.com/vsalavatov/4d609f8f163840525f3346985158400e

Looks like this:

Coroutine StandaloneCoroutine{Active}@1500b2f3, state: SUSPENDED
	at DebugProbesContextKt$main$1$1$1$1.invokeSuspend(DebugProbesContext.kt:24)
	at [CoroutineName(A inner), DispatchedCoroutine{Active}@93a07fa, Dispatchers.Default.limitedParallelism(1)].(DebugProbesContext.kt:21)
	at DebugProbesContextKt$main$1$1$1.invokeSuspend(DebugProbesContext.kt:21)
	at [CoroutineName(A), DispatchedCoroutine{Active}@78d14e01, Dispatchers.IO].(DebugProbesContext.kt:19)
	at DebugProbesContextKt$main$1$1.invokeSuspend(DebugProbesContext.kt:19)kotlin.Unit

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants