From edf587bbf1fc6d5099a49adb5f565562e40020c1 Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Wed, 23 Dec 2020 16:13:57 +0300 Subject: [PATCH] network: fix a bug in discovery with a peer connected twice It could be the case that checks are performed simultaneosly and peers connections goes down from 2 to 0. We must take such case into account and register address as good in discovery. --- pkg/network/server.go | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/pkg/network/server.go b/pkg/network/server.go index dc616f884..88a66071d 100644 --- a/pkg/network/server.go +++ b/pkg/network/server.go @@ -266,7 +266,28 @@ func (s *Server) run() { addr := drop.peer.PeerAddr().String() if drop.reason == errIdenticalID { s.discovery.RegisterBadAddr(addr) - } else if drop.reason != errAlreadyConnected { + } else if drop.reason == errAlreadyConnected { + // There is a race condition when peer can be disconnected twice for the this reason + // which can lead to no connections to peer at all. Here we check for such a possibility. + stillConnected := false + s.lock.RLock() + verDrop := drop.peer.Version() + addr := drop.peer.PeerAddr().String() + if verDrop != nil { + for peer := range s.peers { + ver := peer.Version() + // Already connected, drop this connection. + if ver != nil && ver.Nonce == verDrop.Nonce && peer.PeerAddr().String() == addr { + stillConnected = true + } + } + } + s.lock.RUnlock() + if !stillConnected { + s.discovery.UnregisterConnectedAddr(addr) + s.discovery.BackFill(addr) + } + } else { s.discovery.UnregisterConnectedAddr(addr) s.discovery.BackFill(addr) }