Skip to content

Commit 6902fac

Browse files
committed
Check isCompleted on event loop we're trying to scheduler rather original owner of a task
Fixes #692
1 parent f358547 commit 6902fac

File tree

2 files changed

+40
-5
lines changed

2 files changed

+40
-5
lines changed

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ internal abstract class EventLoopBase: CoroutineDispatcher(), Delay, EventLoop {
261261
_delayed.compareAndSet(null, ThreadSafeHeap())
262262
_delayed.value!!
263263
}
264-
return delayedTask.schedule(delayed)
264+
return delayedTask.schedule(delayed, this)
265265
}
266266

267267
internal fun removeDelayedImpl(delayedTask: DelayedTask) {
@@ -289,7 +289,7 @@ internal abstract class EventLoopBase: CoroutineDispatcher(), Delay, EventLoop {
289289
}
290290
}
291291

292-
internal abstract inner class DelayedTask(
292+
internal abstract class DelayedTask(
293293
timeMillis: Long
294294
) : Runnable, Comparable<DelayedTask>, DisposableHandle, ThreadSafeHeapNode {
295295
private var _heap: Any? = null // null | ThreadSafeHeap | DISPOSED_TASK
@@ -317,9 +317,9 @@ internal abstract class EventLoopBase: CoroutineDispatcher(), Delay, EventLoop {
317317
fun timeToExecute(now: Long): Boolean = now - nanoTime >= 0L
318318

319319
@Synchronized
320-
fun schedule(delayed: ThreadSafeHeap<DelayedTask>): Int {
320+
fun schedule(delayed: ThreadSafeHeap<DelayedTask>, eventLoop: EventLoopBase): Int {
321321
if (_heap === DISPOSED_TASK) return SCHEDULE_DISPOSED // don't add -- was already disposed
322-
return if (delayed.addLastIf(this) { !isCompleted }) SCHEDULE_OK else SCHEDULE_COMPLETED
322+
return if (delayed.addLastIf(this) { !eventLoop.isCompleted }) SCHEDULE_OK else SCHEDULE_COMPLETED
323323
}
324324

325325
// note: DefaultExecutor.schedule performs `schedule` (above) which does sync & checks for DISPOSED_TASK
@@ -352,7 +352,7 @@ internal abstract class EventLoopBase: CoroutineDispatcher(), Delay, EventLoop {
352352
}
353353

354354
// Cannot be moved to DefaultExecutor due to BE bug
355-
internal inner class DelayedRunnableTask(
355+
internal class DelayedRunnableTask(
356356
time: Long,
357357
private val block: Runnable
358358
) : DelayedTask(time) {

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

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,39 @@ class RunBlockingTest : TestBase() {
103103
finish(4)
104104
}
105105
}
106+
107+
@Test(expected = CancellationException::class)
108+
fun testDispatchOnShutdown() = runBlocking<Unit> {
109+
expect(1)
110+
val job = launch(NonCancellable) {
111+
try {
112+
expect(2)
113+
delay(Long.MAX_VALUE)
114+
} finally {
115+
finish(4)
116+
}
117+
}
118+
119+
yield()
120+
expect(3)
121+
coroutineContext.cancel()
122+
job.cancel()
123+
}
124+
125+
@Test(expected = CancellationException::class)
126+
fun testDispatchOnShutdown2() = runBlocking<Unit> {
127+
coroutineContext.cancel()
128+
expect(1)
129+
val job = launch(NonCancellable, start = CoroutineStart.UNDISPATCHED) {
130+
try {
131+
expect(2)
132+
delay(Long.MAX_VALUE)
133+
} finally {
134+
finish(4)
135+
}
136+
}
137+
138+
expect(3)
139+
job.cancel()
140+
}
106141
}

0 commit comments

Comments
 (0)