Skip to content
This repository was archived by the owner on Aug 30, 2022. It is now read-only.

Conversation

@twyatt
Copy link
Member

@twyatt twyatt commented Oct 26, 2018

Typical behavior of Channel is to throw a ClosedReceiveChannelException on invocation of close if a receive is suspended. This is unfortunately a bit counter intuitive and can produce misleading stacktraces (i.e. stacktrace will include close invocation but not receive).

The following simplified snippets illustrate the issue:

Exception in thread "main" kotlinx.coroutines.channels.ClosedReceiveChannelException: Channel was closed
    at kotlinx.coroutines.channels.Closed.getReceiveException(AbstractChannel.kt:1070)
    at kotlinx.coroutines.channels.AbstractChannel$ReceiveElement.resumeReceiveClosed(AbstractChannel.kt:914)
    at kotlinx.coroutines.channels.AbstractSendChannel.helpClose(AbstractChannel.kt:320)
    at kotlinx.coroutines.channels.AbstractSendChannel.close(AbstractChannel.kt:256)
    at kotlinx.coroutines.channels.SendChannel$DefaultImpls.close$default(Channel.kt:94)
    at MainKt$main$1$2.invokeSuspend(Main.kt:17)
    at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
    ...
    at MainKt.main(Main.kt:7)
fun main(args: Array<String>) = runBlocking<Unit> {
    val channel = Channel<Int>(CONFLATED)

    launch {
        channel.receive() // Expected stacktrace to include this line, but it did not. :(
    }

    // Assuming another thread goes to shutdown our task:
    launch {
        delay(200L)
        channel.close() // Appears in stacktrace as: MainKt$main$1$2.invokeSuspend(Main.kt:17)
    }
}

In order to be more explicit with our exception stacktraces related to Channel cancelation: catching ClosedReceiveChannelException and explicitly throwing GattClosed exception (that carries original exception as it's cause).

May need to revisit this behavior in the future after receiveOrClosed is implemented per Kotlin/kotlinx.coroutines#330. Also noteworthy is that receiveOrNull was undeprecated via Kotlin/kotlinx.coroutines#739.

Typical behavior of `Channel` is to throw a
`ClosedReceiveChannelException` on invocation of `close` if a `receive`
is suspended. This is unfortunately a bit counter intuitive and can
produce misleading stacktraces.

In order to be more explicit with our exception stacktraces related to
`Channel` cancelation, using `receiveOrNull` and explicitly throwing
`GattClosed` exception when receiving `null`.

May need to revisit this behavior in the future after `receiveOrClosed`
is implemented per Kotlin/kotlinx.coroutines#330. Also noteworthy is
that `receiveOrNull` was undeprecated via Kotlin/kotlinx.coroutines#739.
@twyatt twyatt requested review from ebabel and nachtien October 26, 2018 21:59
@twyatt twyatt merged commit 834f6ce into develop Oct 29, 2018
@twyatt twyatt deleted the travis/GattClosed branch October 29, 2018 20:39
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants