-
Notifications
You must be signed in to change notification settings - Fork 15
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
Closing a session should not block #78
Comments
closing is definitely non blocking - what you see is the async We've come to learn that timeouts are (almost) always better handled by the calling application and not internally. In other words, if a timeout for await ws.close().wait(1.minutes) This should cancel the That said, cancellation is not tested and it's definitely something to add sooner rather than later, along with chronos trackers (#72). |
does |
Sorry, when I say "blocking", I mean in the context of async, but I should say "closing is not instantaneous" So with the current setup of But it's not done everywhere, here it's simply awaited in a conn event handler, and the conn event handler is awaited inside the connection manager, which will now block whichever function called So we should either:
For me, 3 is the best option. 1 seems risky, because it's the type of issues that could clog up an application main loop unexpectedly (especially since this only happens with user space transports!). 2 could also work, but imo it's better to use the same logic here as the others transports stack, which is to have an instantaneous close, and cleanup in the background. And so if we go with 3, proc close(s: Sock) =
if s.closed: return
s.closed = true
asyncSpawn(actuallyClose()) So the end application won't be able to specify a timeout to To recap, I think this library should copy as much as possible the behavior of kernel space protocols, to avoid unexpected behavior for the applications using it. And in kernel space network protocols, |
consider that the OS also doesn't close things at once - if you are waiting for a "read" event, you will receive the notification after the socket has closed if you close it from somewhere else - the one thing we've done in libp2p is that we tend to ignore errors during close and drop the future / spawn it, even if say there are writes queued etc |
libp2p assumes half-closed (mplex/yamux/etc) streams, meaning that a full close is not performed until all data has been sent/read, so there is (almost) always a delay between calling When talking about closing actual raw socket/connection, closing happens only when the transport, connection manager or muxer is shutting down - nothing else has access to it right now. On top of that, there is already a failsafe timeout at the All this to say that fundamentally nothing has changed with the introduction of websockets, the only difference right now is that when calling In the majority of cases, when there is a public api available, as it is the case here with There are some potential exceptions to this rule, for example, it's impossible to attach a timeout to an |
As a complement and to confirm that we're doing it right, here is an example of how to perform close using Berkley sockets as an analogy - https://datatracker.ietf.org/doc/html/rfc6455#section-7.1.1
This is exactly what |
Discussed at today's meeting, And I'll add a timeout inside libp2p |
Just to clarify, in chronos, calling |
If we follow the logic of TCP etc, a
close
call on a session should not block, and should instead close in the background (for instance withasyncSpawn
)It would also make sense to add a timeout to the close operation, since a non-responsive peer could block indefinitely
The text was updated successfully, but these errors were encountered: