Skip to content

Commit fd42442

Browse files
qwwdfsadelizarov
authored andcommitted
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 313978c commit fd42442

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

Lines changed: 4 additions & 4 deletions
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

Lines changed: 16 additions & 0 deletions
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)