From b28cdb31f9668a6a2abf9eec163e00e8690f5983 Mon Sep 17 00:00:00 2001 From: Max Inden Date: Mon, 4 Jul 2022 03:58:16 +0200 Subject: [PATCH] protocols/identify: Fix race condition in discover_peer_after_disconnect (#2744) **Summary** of the plot of the `discover_peer_after_disconnect` test: 1. `swarm2` connects to `swarm1`. 2. `swarm2` requests an identify response from `swarm1`. 3. `swarm1` sends the response to `swarm2`. 4. `swarm2` disconnects from `swarm1`. 5. `swarm2` tries to disconnect. **Problem** `libp2p-identify` sets `KeepAlive::No` when it identified the remote. Thus `swarm1` might identify` `swarm2` before `swarm2` identified `swarm1`. `swarm1` then sets `KeepAlive::No` and thus closes the connection to `swarm2` before `swarm2` identified `swarm1`. In such case the unit test `discover_peer_after_disconnect hangs indefinitely. **Solution** Add an initial delay to `swarm1` requesting an identification from `swarm2`, thus ensuring `swarm2` is always able to identify `swarm1`. --- protocols/identify/src/identify.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/protocols/identify/src/identify.rs b/protocols/identify/src/identify.rs index 5e82b8e43e6..1bfab2d84e5 100644 --- a/protocols/identify/src/identify.rs +++ b/protocols/identify/src/identify.rs @@ -518,6 +518,7 @@ mod tests { use libp2p::tcp::TcpConfig; use libp2p_core::{identity, muxing::StreamMuxerBox, transport, upgrade, PeerId, Transport}; use libp2p_swarm::{Swarm, SwarmEvent}; + use std::time::Duration; fn transport() -> ( identity::PublicKey, @@ -700,7 +701,14 @@ mod tests { let mut swarm1 = { let (pubkey, transport) = transport(); - let protocol = Identify::new(IdentifyConfig::new("a".to_string(), pubkey.clone())); + let protocol = Identify::new( + IdentifyConfig::new("a".to_string(), pubkey.clone()) + // `swarm1` will set `KeepAlive::No` once it identified `swarm2` and thus + // closes the connection. At this point in time `swarm2` might not yet have + // identified `swarm1`. To give `swarm2` enough time, set an initial delay on + // `swarm1`. + .with_initial_delay(Duration::from_secs(10)), + ); Swarm::new(transport, protocol, pubkey.to_peer_id()) };