From 89a1e0fb240b17722cecd8ecf2f9c21c7730cc90 Mon Sep 17 00:00:00 2001 From: Matthias Radestock Date: Sun, 30 Nov 2014 15:48:46 +0000 Subject: [PATCH] eliminate a deadlock Golang locks aren't re-entrant. As result one can get deadlocks on RWMutexes like this: goroutine #1: attempt to acquire read lock -> success goroutine #2: attempt to acquire write lock -> wait goroutine #1: attempt to acquire read lock again -> wait (a pending write lock prevents subsequent acquisitions of read locks) Peer.HasPathTo could run into this since it could attempt to acquire the read lock on a peer multiple times if previously it had encountered that peer via an asymmetric connection. --- router/peer.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/router/peer.go b/router/peer.go index 6c08afd3..e7facb1b 100644 --- a/router/peer.go +++ b/router/peer.go @@ -90,10 +90,12 @@ func (peer *Peer) HasPathTo(target *Peer, symmetric bool) (bool, map[PeerName]bo // made to that path during our calculation. remote := conn.Remote() remote.RLock() - defer remote.RUnlock() if _, found := remote.connections[curPeer.Name]; !symmetric || found { + defer remote.RUnlock() nextWorklist = append(nextWorklist, remote) reached[remoteName] = true + } else { + remote.RUnlock() } } }