Skip to content

Commit 773eb59

Browse files
committed
Implement CoroutineStackFrame in SelectBuilderImpl
Fixes #931
1 parent c055f02 commit 773eb59

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

kotlinx-coroutines-core/common/src/selects/Select.kt

+6-1
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,12 @@ private val RESUMED: Any = Symbol("RESUMED")
197197
internal class SelectBuilderImpl<in R>(
198198
private val uCont: Continuation<R> // unintercepted delegate continuation
199199
) : LockFreeLinkedListHead(), SelectBuilder<R>,
200-
SelectInstance<R>, Continuation<R> {
200+
SelectInstance<R>, Continuation<R>, CoroutineStackFrame {
201+
override val callerFrame: CoroutineStackFrame?
202+
get() = uCont as? CoroutineStackFrame
203+
204+
override fun getStackTraceElement(): StackTraceElement? = null
205+
201206
// selection state is "this" (list of nodes) initially and is replaced by idempotent marker (or null) when selected
202207
private val _state = atomic<Any?>(this)
203208

kotlinx-coroutines-debug/test/SanitizedProbesTest.kt

+43
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package definitely.not.kotlinx.coroutines
77

88
import kotlinx.coroutines.*
99
import kotlinx.coroutines.debug.*
10+
import kotlinx.coroutines.selects.*
1011
import org.junit.*
1112
import org.junit.Test
1213
import java.util.concurrent.*
@@ -83,6 +84,48 @@ class SanitizedProbesTest : TestBase() {
8384
deferred.cancelAndJoin()
8485
}
8586

87+
@Test
88+
fun testSelectBuilder() = runTest {
89+
val selector = launchSelector()
90+
expect(1)
91+
yield()
92+
expect(3)
93+
verifyDump("Coroutine \"coroutine#1\":BlockingCoroutine{Active}@35fc6dc4, state: RUNNING (Last suspension stacktrace, not an actual stacktrace)\n" +
94+
"\t(Coroutine creation stacktrace)\n" +
95+
"\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)",
96+
97+
"Coroutine \"coroutine#2\":StandaloneCoroutine{Active}@1b68b9a4, state: SUSPENDED\n" +
98+
"\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$launchSelector\$1\$1\$1.invokeSuspend(SanitizedProbesTest.kt:105)\n" +
99+
"\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$launchSelector\$1.invokeSuspend(SanitizedProbesTest.kt:143)\n" +
100+
"\t(Coroutine creation stacktrace)\n" +
101+
"\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" +
102+
"\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:25)\n" +
103+
"\tat kotlinx.coroutines.BuildersKt.launch\$default(Unknown Source)\n" +
104+
"\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.launchSelector(SanitizedProbesTest.kt:100)\n" +
105+
"\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.access\$launchSelector(SanitizedProbesTest.kt:16)\n" +
106+
"\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest\$testSelectBuilder\$1.invokeSuspend(SanitizedProbesTest.kt:89)\n" +
107+
"\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)\n" +
108+
"\tat kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:233)\n" +
109+
"\tat kotlinx.coroutines.TestBase.runTest\$default(TestBase.kt:154)\n" +
110+
"\tat definitely.not.kotlinx.coroutines.SanitizedProbesTest.testSelectBuilder(SanitizedProbesTest.kt:88)")
111+
finish(4)
112+
selector.cancelAndJoin()
113+
}
114+
115+
private fun CoroutineScope.launchSelector(): Job {
116+
val job = CompletableDeferred(Unit)
117+
return launch {
118+
select<Int> {
119+
job.onJoin {
120+
expect(2)
121+
delay(Long.MAX_VALUE)
122+
1
123+
}
124+
125+
}
126+
}
127+
}
128+
86129
private fun CoroutineScope.createActiveDeferred(): Deferred<*> = async {
87130
suspendingMethod()
88131
assertTrue(true)

0 commit comments

Comments
 (0)