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

Throw GattClosed if Gatt is closed during I/O operation #23

Merged
merged 2 commits into from Oct 29, 2018

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 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.

None yet

3 participants