-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SendChannel.offer should never throw #974
Comments
We can actually have a slightly different proposal in mind:
where a See also #330 |
I think the "OrClosed" suffixed functions would greatly fit the use cases where you need to know the channel was closed. If the "OrClosed" suffixed functions make it to a release, would the |
I don't have an answer on the last question yet. Indeed, we are running into this and some other issues that might require us tweaking semantics of channels with respect to the close operations, however it is not clear how we could introduce those changing without breaking a lot of code. |
I wonder if someone ever caught that closed exception satisfying a use case with this behavior. |
Somebody might have been offering elements to a channel until it is closed relying on an exception to abort this offering loop on channel close. |
This is only my two cents, but I think it's more likely that people have been bitten by That's why I think adding The benefit to addressing this issue that way IMHO are that |
Will fix rare crashes caused by uncaught exception that could be throw from the onConnectionStateChange method in GattConnectionImpl. Related to Kotlin/kotlinx.coroutines#974
I have had several bugs in production because of this, it’s especially bad in Android where it will likely crash the app and since Kotlin doesn’t have checked exceptions it’s very easy to forget even if you’ve been bitten before. I agree that it doesn’t seem very likely that anyone is relying on this behavior. |
Now that the |
|
I've been bitten by that again just now (plus earlier)! I know a bunch of code using That causes problems as the unregister can happen after the channel is closed if it's not taking place on the same thread and Please, can you integrate a safe alternative to that before Kotlin 1.4? It'll be almost one year I reported this issue in less than a month. |
+1 to that. I’ve chosen to never |
You can just use this: fun <E> SendChannel<E>.sendBlockingOrNull(element: E) = try {
sendBlocking(element)
} catch (e: ClosedSendChannelException) {
null
} But I agree, I wish |
I use runCatching around offer (or a try catch), because I don't need to launch a coroutine in callbacks. |
Got to this issue via @LouisCAD from a post on the Kotlin slack channel. I reported getting crashes on my Android app for a CancellationException with no stacktrace;
This is a huge project, that was built with kotlin and coroutines from the ground up. There's heavy usage of offer (for better or for worse) and to handle each case would be a giant undertaking, let alone first figuring out where this crash is coming from. Granted, I never read the docs closely enough to notice the caveat about throwing if it's closed, but I assumed it was a safe call because it returns Boolean. |
As said on Slack:
|
Please don't change the semantics of existing API without major version change and/or deprecation cycle! I totally agree that For example think of actors or any other process on the other side of the channel:
These are two totally different scenarios and execution paths. Currently
But I am all for introducing safer functions and very much like the |
I've just been bitten by that too (See apollographql/apollo-kotlin#2005 for some context). The I've opened a PR there to improve the aforementioned snippet. |
@qwwdfsad Could you please clarify if this issue is fixed in 1.4.0, which was released today? |
We still willing to fix it in 1.4.x |
@qwwdfsad any progress on this? My team won't let me use |
@nachtien this issue has a workaround. Unless you need binary compatibility reaching very very far into the future, I see no reason to not use Experimental is for the API, it doesn't mean the thing is specially risky to use or that it doesn't work. |
Right, but my team says "no experimental ever", no matter what I say, thus i can't use this. |
You could always fork this library and remove the experimental annotations in your fork, then use that. Then nothing will change by surprise, ever! You just then have to keep pulling changes from this repo into your own, but you'd have full control over what changes to bring in. I would not recommend this approach generally (because, as Louis said, there's no real reason to not use experimental APIs in something that's not a library), but if you have very strong restrictions around API stability, it's one potential solution. |
There's 4 other possibilities if they don't try to understand what experimental stands for in this particular case:
Disclaimer: These might all be bad ideas 😄 |
Is the plan of resolution for this issue to evolve the API so it uses Kotlin 1.5 |
…cement for error-prone offer, poll and receiveOrNull Fixes #974
…cement for error-prone offer, poll and receiveOrNull Fixes #974
…cement for error-prone offer, poll and receiveOrNull Fixes #974
We've studied our channel API surface and tried to work towards not only with the new method name instead of When looking at the new API with TBD names, whether it's "catching offer" or "receiveOrClosed", the very first thing that comes to mind is that these methods try to do the same thing -- error encapsulation. Other languages have built-in constructs for that, e.g. So, maybe just adding
Orthogonally, Kotlin has Taking it into account and the fact, that
|
I strongly vote for a domain specific class, I am not really happy of |
…ages along the codebase (#2644) * Deprecate SendChannel.offer and replace its usages along the codebase * Deprecate ReceiveChannel.poll and replace its usages along the codebase Co-authored-by: Roman Elizarov <[email protected]> Addresses #974
|
…cement for error-prone offer, poll and receiveOrNull Fixes Kotlin#974
…ages along the codebase (Kotlin#2644) * Deprecate SendChannel.offer and replace its usages along the codebase * Deprecate ReceiveChannel.poll and replace its usages along the codebase Co-authored-by: Roman Elizarov <[email protected]> Addresses Kotlin#974
As of version 1.1.1, if you call
offer
from the non blocking world (which doesn't handleCancellationException
by default, on a closedChannel
, an exception is thrown, which by default will crash the program.This is a problem in several ways:
offer
which returns aBoolean
per its signature actually is kind of a "tri-lean" as if the channel is closed, it will not returnfalse
but throw.offer
is possibly called from a thread that is not the one where the callback that offers the values is unregistered, so race conditions may implyoffer
being called once or a few times after the channel is closed, and usually, the intention is to ignore those. Simply returningfalse
instead of throwing would likely be a better behavior.offer
without having this function possibly throw, because by the timeisClosedForSend
returnsfalse
, it may have been closed due to concurrent execution, so a subsequent call tooffer
would throw.My current workaround is the following:
The text was updated successfully, but these errors were encountered: