-
Notifications
You must be signed in to change notification settings - Fork 996
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
Race condition while waiting on all listen interfaces #3305
Comments
Can you expand on why you can not handle the other events right away?
I am not familiar enough with your use-case. Off the top of my head, this seems like a hack that you can easily implement on top of |
We'd like to handle those events straight away, however we have based our code on dcutr, and as dcutr we first wait to listen on all interfaces, then we dial other peers. Do you known why dcutr is written this way ? That is to say we have removed the first wait listen loop in our code and it seems to be ok, but the interrogation still remains.
Yes for sure, it can be implemented by buffering the events but seems to be a bit ugly. |
Another approach could be to send all swarm events to multiple recipients: one is the long-running loop that services all swarm requests, another is a stream consumer that just filters for NewListenAddr events and does whatever you need to do with those. One potentially nice feature to be added to libp2p might be to emit an event once the listeners on all initially detected interfaces have been bound (or failed to do so). I’m a bit on the fence, though, whether a more sustainable design is enforced by only emitting addresses as they appear — since that can happen at any later time anyway. @stormshield-pj50 this is the crux of the matter: you typically will get NewListenAddr later, after other events have been emitted, so when would you decide to say “now the listening phase is complete”? |
It is a standalone example that doesn't necessarily represent the way you'd structure a production application. |
I understand this is not a production application, but how can you dial and make port reuse work if you haven't waited first to listen on all interfaces ? How would you do that in a production application ? Can you provide an example code ? |
@stormshield-pj50 Could you be more precise? I ask because “all interfaces” is not well-defined: interfaces may appear or disappear at any time, and they may or may not be enumerated within a given timeout. The situation would be completely different if your application listens on specific addresses, in which case you know all addresses from the start. (I don’t know much about dcutr, so take my comments as generic Swarm statements.) |
Yes I mean "all interfaces" like in dcutr by listening on 0.0.0.0, so I don't know all addresses from the start. |
That’s what I said: binding to What you could do is use |
Are you starting your applications at the same time? Normally the order of events should be:
If I understand your setup correctly, the "race condition" you are experiencing is because Client A magically knows the relay's address ahead of time. If it were to learn it at runtime, the In both cases, I think the race condition should not occur. Bottom line: The example takes a short-cut by having the client learn the relay's address "out-of-band" via a commandline parameter. This design is prone to race conditions so that is the bit you should likely get rid of. Hope that helps :) |
@stormshield-pj50 I am closing this as resolved. Please let me know if there is still an issue you think needs addressing! :) |
Summary
We have some code based on the dcutr example that starts a first event loop and wait on all listen interfaces for one second. Our code can act both as a client (listener + dialer) and a server (listener only).
We are experimenting a race condition while waiting on all listen interfaces: both NewListenAddr and incoming ConnectionEstablished events can be received if for instance an other peer dial the peer at the same time. One possible fix is to explicitly handle the ConnectionEstablished event but we could also miss other events (SwarmEvent::Behaviour events, ...).
Expected behaviour
When starting get all listen interfaces through NewListenAddr events, and then receive other events.
Actual behaviour
Listen interfaces events are mixed with other kind of events.
Possible Solution
Provide a swarm API that can filter in events. Filtered out events are kept in the swarm for later usage.
Version
0.50.0
Would you like to work on this bug ?
Maybe, depending on the proposed solution and its complexity.
The text was updated successfully, but these errors were encountered: