Skip to content

Commit addff4b

Browse files
authored
Prevent potential re-park when the unparking thread is too slow (#2381)
1 parent 937cc0c commit addff4b

File tree

2 files changed

+14
-2
lines changed

2 files changed

+14
-2
lines changed

kotlinx-coroutines-core/jvm/src/scheduling/CoroutineScheduler.kt

+13-1
Original file line numberDiff line numberDiff line change
@@ -721,7 +721,19 @@ internal class CoroutineScheduler(
721721
}
722722
assert { localQueue.size == 0 }
723723
workerCtl.value = PARKED // Update value once
724-
while (inStack()) { // Prevent spurious wakeups
724+
/*
725+
* inStack() prevents spurious wakeups, while workerCtl.value == PARKED
726+
* prevents the following race:
727+
*
728+
* - T2 scans the queue, adds itself to the stack, goes to rescan
729+
* - T2 suspends in 'workerCtl.value = PARKED' line
730+
* - T1 pops T2 from the stack, claims workerCtl, suspends
731+
* - T2 fails 'while (inStack())' check, goes to full rescan
732+
* - T2 adds itself to the stack, parks
733+
* - T1 unparks T2, bails out with success
734+
* - T2 unparks and loops in 'while (inStack())'
735+
*/
736+
while (inStack() && workerCtl.value == PARKED) { // Prevent spurious wakeups
725737
if (isTerminated || state == WorkerState.TERMINATED) break
726738
tryReleaseCpu(WorkerState.PARKING)
727739
interrupted() // Cleanup interruptions

kotlinx-coroutines-core/jvm/test/scheduling/BlockingCoroutineDispatcherMixedStealingStressTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,4 @@ class BlockingCoroutineDispatcherMixedStealingStressTest : SchedulerTestBase() {
7777
cpuBlocker.await()
7878
}
7979
}
80-
}
80+
}

0 commit comments

Comments
 (0)