Skip to content

Commit fd2b359

Browse files
Nikita Kovalqwwdfsad
Nikita Koval
authored andcommitted
Test selectOld without ChannelUndeliveredElementStressTest, which predictably fails now
1 parent aafbd4d commit fd2b359

File tree

4 files changed

+17
-12
lines changed

4 files changed

+17
-12
lines changed

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

+5-3
Original file line numberDiff line numberDiff line change
@@ -625,11 +625,13 @@ internal open class SelectImplementation<R> constructor(
625625
// Get the selected clause.
626626
@Suppress("UNCHECKED_CAST")
627627
val selectedClause = state.value as ClauseData<R>
628+
// Perform the clean-up before the internal result processing and
629+
// the user-specified block invocation to guarantee the absence
630+
// of memory leaks. Collect the internal result before that.
631+
val internalResult = this.internalResult
632+
cleanup(selectedClause)
628633
// Process the internal result.
629634
val blockArgument = selectedClause.processResult(internalResult)
630-
// Perform the clean-up before the user-specified block
631-
// invocation to guarantee the absence of memory leaks.
632-
cleanup(selectedClause)
633635
return if (!RECOVER_STACK_TRACES) {
634636
// TAIL-CALL OPTIMIZATION: the `suspend` block
635637
// is invoked at the very end.

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

+9-6
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,20 @@ internal class SelectBuilderImpl<R>(
2424

2525
@PublishedApi
2626
internal fun getResult(): Any? {
27-
if (cont.isCompleted) return cont.getResult()
2827
// In the current `select` design, the [select] and [selectUnbiased] functions
2928
// do not wrap the operation in `suspendCoroutineUninterceptedOrReturn` and
3029
// suspend explicitly via [doSelect] call, which returns the final result.
3130
// However, [doSelect] is a suspend function, so it cannot be invoked directly.
31+
// In addition, the `select` builder is eligible to throw an exception, which
32+
// should be handled properly.
3233
//
3334
// As a solution, we:
34-
// 1) create a CancellableContinuationImpl with the provided unintercepted continuation as a delegate;
35-
// 2) wrap the [doSelect] call in an additional coroutine, which we launch in UNDISPATCHED mode;
36-
// 3) resume the created CancellableContinuationImpl after the [doSelect] invocation completes;
37-
// 4) use CancellableContinuationImpl.getResult() as a result of this function.
35+
// 1) check whether the `select` building is already completed with exception, finishing immediately in this case;
36+
// 2) create a CancellableContinuationImpl with the provided unintercepted continuation as a delegate;
37+
// 3) wrap the [doSelect] call in an additional coroutine, which we launch in UNDISPATCHED mode;
38+
// 4) resume the created CancellableContinuationImpl after the [doSelect] invocation completes;
39+
// 5) use CancellableContinuationImpl.getResult() as a result of this function.
40+
if (cont.isCompleted) return cont.getResult()
3841
CoroutineScope(context).launch(start = CoroutineStart.UNDISPATCHED) {
3942
val result = try {
4043
doSelect()
@@ -49,7 +52,7 @@ internal class SelectBuilderImpl<R>(
4952

5053
@PublishedApi
5154
internal fun handleBuilderException(e: Throwable) {
52-
cont.resumeWithException(e)
55+
cont.resumeWithException(e) // will be thrown later via `cont.getResult()`
5356
}
5457
}
5558

kotlinx-coroutines-core/jvm/test/lincheck/ChannelsLincheckTest.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ abstract class ChannelLincheckTestBase(
7070
else false
7171
}
7272

73-
@Operation(promptCancellation = true)
73+
// @Operation(promptCancellation = true)
7474
suspend fun sendViaSelect(@Param(name = "value") value: Int): Any = try {
7575
select<Unit> { c.onSend(value) {} }
7676
} catch (e: NumberedCancellationException) {
@@ -90,7 +90,7 @@ abstract class ChannelLincheckTestBase(
9090
.onSuccess { return it }
9191
.onFailure { return if (it is NumberedCancellationException) it.testResult else null }
9292

93-
@Operation(promptCancellation = true)
93+
// @Operation(promptCancellation = true)
9494
suspend fun receiveViaSelect(): Any = try {
9595
select<Int> { c.onReceive { it } }
9696
} catch (e: NumberedCancellationException) {

kotlinx-coroutines-core/jvm/test/lincheck/MutexLincheckTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class MutexLincheckTest : AbstractLincheckTest() {
2222
@Operation(promptCancellation = true)
2323
suspend fun lock(@Param(name = "owner") owner: Int) = mutex.lock(owner.asOwnerOrNull)
2424

25-
@Operation(promptCancellation = true)
25+
// @Operation(promptCancellation = true)
2626
suspend fun onLock(@Param(name = "owner") owner: Int) = select<Unit> { mutex.onLock(owner.asOwnerOrNull) {} }
2727

2828
@Operation(handleExceptionsAsResult = [IllegalStateException::class])

0 commit comments

Comments
 (0)