How can I avoid the ClosedByInterruptException fro...
# coroutines
e
How can I avoid the ClosedByInterruptException from being throw up when doing something like this:
Copy code
val test = withTimeoutOrNull(3.seconds) {
    runInterruptible {
        channel.receive(ByteBuffer.allocateDirect(10))
    }
}
I would have expected null to be returned. Catching the exception results in a value being returned instead of null.
j
Why do you use
runInterruptible
here?
channel.receive
is suspending, so I don't see a reason
The point of
runInterruptible
is to convert cancellations from calling code into thread interruption for the wrapped blocking code. If the code is already coroutine-based and supports coroutine cancellation, you shouldn't use
runInterruptible
s
Looking at the code, it looks like he's using
java.nio.channels
đŸ¤” KotlinX Coroutines Channels doesn't have such an API with
ByteBuffer
, does it?
java.nio.channels
don't work with
InterruptedException
it seems, like
runInterruptible
relies on.
u
Well,
ClosedByInterruptException
is not an
InterruptedException
. That’s the issue. In more depth:
runInterruptible
works by catching
InterruptedException
and rethrowing it as
CancellationException
. The issue is here, that
channel.receive
(did you mean channel.read?) catches the `InterruptedException`and rethrows it as
ClosedByInterruptException
which is unknown to
runInterruptible
and breaks everything.
Not nice, but you could do:
Copy code
val test = withTimeoutOrNull(3.seconds) {
    runInterruptible {
        try {
            channel.receive(ByteBuffer.allocateDirect(10))
        }  catch (e: ClosedByInterruptException) {
            throw CancellationException("Blocking call was interrupted due to parent cancellation").initCause(e)
        }
    }
}