Skip to content

Commit 87eaba8

Browse files
elizarovqwwdfsad
authored andcommitted
Fixed cancellation of runBlocking event loon in the presence of delay (#589)
* Fixed cancellation of runBlocking event loon in the presence of delay Fixes #586
1 parent 63e3896 commit 87eaba8

File tree

2 files changed

+31
-4
lines changed

2 files changed

+31
-4
lines changed

core/kotlinx-coroutines-core/src/EventLoop.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,13 @@ internal abstract class EventLoopBase: CoroutineDispatcher(), Delay, EventLoop {
106106

107107
private val nextTime: Long
108108
get() {
109-
if (!isQueueEmpty) return 0
109+
val queue = _queue.value
110+
when {
111+
queue === null -> {} // empty queue -- proceed
112+
queue is Queue<*> -> if (!queue.isEmpty) return 0 // non-empty queue
113+
queue === CLOSED_EMPTY -> return Long.MAX_VALUE // no more events -- closed
114+
else -> return 0 // non-empty queue
115+
}
110116
val delayed = _delayed.value ?: return Long.MAX_VALUE
111117
val nextDelayedTask = delayed.peek() ?: return Long.MAX_VALUE
112118
return (nextDelayedTask.nanoTime - timeSource.nanoTime()).coerceAtLeast(0)

core/kotlinx-coroutines-core/test/RunBlockingTest.kt

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class RunBlockingTest : TestBase() {
4242
runBlocking(coroutineContext) {
4343
expect(3)
4444
// still same event loop
45-
assertTrue(coroutineContext[ContinuationInterceptor] === outerEventLoop)
45+
assertSame(coroutineContext[ContinuationInterceptor], outerEventLoop)
4646
yield() // still works
4747
expect(4)
4848
}
@@ -58,7 +58,7 @@ class RunBlockingTest : TestBase() {
5858
val thread = newSingleThreadContext(name)
5959
runBlocking(thread) {
6060
expect(2)
61-
assertTrue(coroutineContext[ContinuationInterceptor] === thread)
61+
assertSame(coroutineContext[ContinuationInterceptor], thread)
6262
assertTrue(Thread.currentThread().name.contains(name))
6363
yield() // should work
6464
expect(3)
@@ -82,4 +82,25 @@ class RunBlockingTest : TestBase() {
8282
job.cancelAndJoin()
8383
}
8484
}
85-
}
85+
86+
@Test
87+
fun testCancelWithDelay() {
88+
// see https://github.com/Kotlin/kotlinx.coroutines/issues/586
89+
try {
90+
runBlocking {
91+
expect(1)
92+
coroutineContext.cancel()
93+
expect(2)
94+
try {
95+
delay(1)
96+
expectUnreached()
97+
} finally {
98+
expect(3)
99+
}
100+
}
101+
expectUnreached()
102+
} catch (e: JobCancellationException) {
103+
finish(4)
104+
}
105+
}
106+
}

0 commit comments

Comments
 (0)