Take the following program:
package example
import kotlinx.coroutines.InternalCoroutinesApi
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.selects.select
@InternalCoroutinesApi
fun main() {
runBlocking {
val chan = Channel<Unit>()
chan.close()
select<Unit> {
println("Register onReceiveOrClosed.")
chan.onReceiveOrClosed {
println("Selected value $it.")
}
}
println("Done.")
}
}
Running it gives this output:
Register onReceiveOrClosed.
Selected value Closed(null).
Selected value Closed(null).
Exception in thread "main" java.lang.IllegalStateException: Already resumed
at kotlinx.coroutines.selects.SelectBuilderImpl.resumeWith(Select.kt:458)
at kotlinx.coroutines.selects.SelectBuilderImpl.handleBuilderException(Select.kt:309)
at example.ExampleKt$main$1.invokeSuspend(example.kt:28)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:241)
at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:270)
at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:79)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:54)
at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:36)
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
at example.ExampleKt.main(example.kt:10)
at example.ExampleKt.main(example.kt)
I would expect to see just one line Selected value Closed(null)
and I would expect to see no exception (but of course the exception makes sense given that the block given to onReceiveOrClosed
is executed twice).
Is my understanding of onReceiveOrClosed
incorrect or is this a bug with onReceiveOrClosed
?
I'm using Kotlin 1.3.50 and kotlinx-coroutines-core:1.3.1
. The full example is available here: https://github.com/frececroka/kotlin-select-onreceiveorclosed.
I think it's because when you call
select
the channel is already closed. If you add some delay, it will work fine:I'm not sure is this a bug or intended behavior