Skip to content

Commit 37d5dc7

Browse files
author
jiaoxiaodong
committed
Rethrow AbortFlowException upon cancellation (#4034)
collectWhile catches AbortFlowException even if the CoroutineScope is cancelled while waiting on child tasks, causing it to fail to respond to cancel().
1 parent 1fcffbf commit 37d5dc7

File tree

2 files changed

+23
-1
lines changed

2 files changed

+23
-1
lines changed

kotlinx-coroutines-core/common/src/flow/operators/Limit.kt

+3
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package kotlinx.coroutines.flow
55

66
import kotlinx.coroutines.*
77
import kotlinx.coroutines.flow.internal.*
8+
import kotlin.coroutines.*
89
import kotlin.jvm.*
910
import kotlinx.coroutines.flow.flow as safeFlow
1011
import kotlinx.coroutines.flow.internal.unsafeFlow as flow
@@ -133,5 +134,7 @@ internal suspend inline fun <T> Flow<T>.collectWhile(crossinline predicate: susp
133134
collect(collector)
134135
} catch (e: AbortFlowException) {
135136
e.checkOwnership(collector)
137+
// The task might have been cancelled before AbortFlowException was thrown.
138+
coroutineContext.ensureActive()
136139
}
137140
}

kotlinx-coroutines-core/common/test/flow/terminal/FirstTest.kt

+20-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ package kotlinx.coroutines.flow
22

33
import kotlinx.coroutines.testing.*
44
import kotlinx.coroutines.*
5+
import kotlinx.coroutines.CoroutineStart.*
56
import kotlinx.coroutines.channels.*
67
import kotlinx.coroutines.flow.internal.*
78
import kotlin.test.*
9+
import kotlin.time.*
810

911
class FirstTest : TestBase() {
1012
@Test
@@ -173,4 +175,21 @@ class FirstTest : TestBase() {
173175

174176
assertFailsWith<CancellationException> { flow.first() }
175177
}
176-
}
178+
179+
@Test
180+
fun testFirstThrowOnCancellation() = runTest {
181+
val job = launch(start = UNDISPATCHED) {
182+
flow {
183+
try {
184+
emit(Unit)
185+
} finally {
186+
runCatching { yield() }
187+
finish(2)
188+
}
189+
}.first()
190+
expectUnreached()
191+
}
192+
expect(1)
193+
job.cancel()
194+
}
195+
}

0 commit comments

Comments
 (0)