Skip to content

Commit 6d6275d

Browse files
committed
Invoke exception handler for actor on cancellation even when channel was successfully closed, so exceptions thrown by actor are always reported
Fixes #368
1 parent a432a82 commit 6d6275d

File tree

2 files changed

+20
-4
lines changed
  • core/kotlinx-coroutines-core/src
    • main/kotlin/kotlinx/coroutines/experimental/channels
    • test/kotlin/kotlinx/coroutines/experimental/channels

2 files changed

+20
-4
lines changed

core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/channels/Actor.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,9 @@ private open class ActorCoroutine<E>(
163163
active: Boolean
164164
) : ChannelCoroutine<E>(parentContext, channel, active), ActorScope<E>, ActorJob<E> {
165165
override fun onCancellation(cause: Throwable?) {
166-
if (!_channel.cancel(cause) && cause != null)
167-
handleCoroutineException(context, cause)
166+
_channel.cancel(cause)
167+
// Always propagate the exception, don't wait for actor senders
168+
if (cause != null) handleCoroutineException(context, cause)
168169
}
169170
}
170171

@@ -178,7 +179,7 @@ private class LazyActorCoroutine<E>(
178179
block.startCoroutineCancellable(this, this)
179180
}
180181

181-
suspend override fun send(element: E) {
182+
override suspend fun send(element: E) {
182183
start()
183184
return super.send(element)
184185
}
@@ -197,4 +198,3 @@ private class LazyActorCoroutine<E>(
197198
super.onSend.registerSelectClause2(select, param, block)
198199
}
199200
}
200-

core/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ActorTest.kt

+16
Original file line numberDiff line numberDiff line change
@@ -146,4 +146,20 @@ class ActorTest(private val capacity: Int) : TestBase() {
146146

147147
finish(3)
148148
}
149+
150+
@Test
151+
fun testThrowingActor() = runTest(unhandled = listOf({e -> e is IllegalArgumentException})) {
152+
val parent = Job()
153+
val actor = actor<Int>(context = coroutineContext, parent = parent) {
154+
channel.consumeEach {
155+
expect(1)
156+
throw IllegalArgumentException()
157+
}
158+
}
159+
160+
actor.send(1)
161+
parent.cancel()
162+
parent.join()
163+
finish(2)
164+
}
149165
}

0 commit comments

Comments
 (0)