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
Joffrey
11/14/2022, 8:48 AM
Why do you use
runInterruptible
here?
channel.receive
is suspending, so I don't see a reason
Joffrey
11/14/2022, 8:49 AM
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
simon.vergauwen
11/14/2022, 9:52 AM
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?
simon.vergauwen
11/14/2022, 9:53 AM
java.nio.channels
don't work with
InterruptedException
it seems, like
runInterruptible
relies on.
u
uli
11/14/2022, 2:22 PM
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.
uli
11/14/2022, 2:24 PM
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)
}
}
}