Skip to content

Commit 4a5892f

Browse files
authored
Properly use UndispatchedCoroutine context for context-specific elements (#3413)
Fixes #3411
1 parent bb16214 commit 4a5892f

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

kotlinx-coroutines-core/common/src/Builders.common.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ public suspend fun <T> withContext(
163163
if (newContext[ContinuationInterceptor] == oldContext[ContinuationInterceptor]) {
164164
val coroutine = UndispatchedCoroutine(newContext, uCont)
165165
// There are changes in the context, so this thread needs to be updated
166-
withCoroutineContext(newContext, null) {
166+
withCoroutineContext(coroutine.context, null) {
167167
return@sc coroutine.startUndispatchedOrReturn(coroutine, block)
168168
}
169169
}

kotlinx-coroutines-core/jvm/test/ThreadContextElementTest.kt

+35
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,41 @@ class ThreadContextElementTest : TestBase() {
156156
}
157157
}
158158
}
159+
160+
class JobCaptor(val capturees: ArrayList<Job> = ArrayList()) : ThreadContextElement<Unit> {
161+
162+
companion object Key : CoroutineContext.Key<MyElement>
163+
164+
override val key: CoroutineContext.Key<*> get() = Key
165+
166+
override fun updateThreadContext(context: CoroutineContext) {
167+
capturees.add(context.job)
168+
}
169+
170+
override fun restoreThreadContext(context: CoroutineContext, oldState: Unit) {
171+
}
172+
}
173+
174+
@Test
175+
fun testWithContextJobAccess() = runTest {
176+
val captor = JobCaptor()
177+
val manuallyCaptured = ArrayList<Job>()
178+
runBlocking(captor) {
179+
manuallyCaptured += coroutineContext.job
180+
withContext(CoroutineName("undispatched")) {
181+
manuallyCaptured += coroutineContext.job
182+
withContext(Dispatchers.IO) {
183+
manuallyCaptured += coroutineContext.job
184+
}
185+
// Context restored, captured again
186+
manuallyCaptured += coroutineContext.job
187+
}
188+
// Context restored, captured again
189+
manuallyCaptured += coroutineContext.job
190+
}
191+
192+
assertEquals(manuallyCaptured, captor.capturees)
193+
}
159194
}
160195

161196
class MyData

0 commit comments

Comments
 (0)