discovery: fix deadlock by ensure we don't hold sync mutex during send

In this commit, we fix an existing deadlock in the
gossiper->server->peer pipeline by ensuring that we're not holding the
syncer mutex while we attempt to have a syncer filter out the rest of
gossip messages.
This commit is contained in:
Olaoluwa Osuntokun 2018-06-04 16:50:04 -07:00
parent a9340d22c4
commit 0ec4a06e6b
No known key found for this signature in database
GPG Key ID: 964EA263DD637C21

@ -525,7 +525,7 @@ type msgWithSenders struct {
// with peers that we have an active gossipSyncer with. We do this to ensure // with peers that we have an active gossipSyncer with. We do this to ensure
// that we don't broadcast messages to any peers that we have active gossip // that we don't broadcast messages to any peers that we have active gossip
// syncers for. // syncers for.
func (m *msgWithSenders) mergeSyncerMap(syncers map[routing.Vertex]struct{}) { func (m *msgWithSenders) mergeSyncerMap(syncers map[routing.Vertex]*gossipSyncer) {
for peerPub := range syncers { for peerPub := range syncers {
m.senders[peerPub] = struct{}{} m.senders[peerPub] = struct{}{}
} }
@ -1130,9 +1130,9 @@ func (d *AuthenticatedGossiper) networkHandler() {
// syncers, we'll collect their pubkeys so we can avoid // syncers, we'll collect their pubkeys so we can avoid
// sending them the full message blast below. // sending them the full message blast below.
d.syncerMtx.RLock() d.syncerMtx.RLock()
syncerPeers := map[routing.Vertex]struct{}{} syncerPeers := make(map[routing.Vertex]*gossipSyncer)
for peerPub := range d.peerSyncers { for peerPub, syncer := range d.peerSyncers {
syncerPeers[peerPub] = struct{}{} syncerPeers[peerPub] = syncer
} }
d.syncerMtx.RUnlock() d.syncerMtx.RUnlock()
@ -1142,11 +1142,9 @@ func (d *AuthenticatedGossiper) networkHandler() {
// We'll first attempt to filter out this new message // We'll first attempt to filter out this new message
// for all peers that have active gossip syncers // for all peers that have active gossip syncers
// active. // active.
d.syncerMtx.RLock() for _, syncer := range syncerPeers {
for _, syncer := range d.peerSyncers {
syncer.FilterGossipMsgs(announcementBatch...) syncer.FilterGossipMsgs(announcementBatch...)
} }
d.syncerMtx.RUnlock()
// Next, If we have new things to announce then // Next, If we have new things to announce then
// broadcast them to all our immediately connected // broadcast them to all our immediately connected
@ -1234,8 +1232,7 @@ func (d *AuthenticatedGossiper) PruneSyncState(peer *btcec.PublicKey) {
peer.SerializeCompressed()) peer.SerializeCompressed())
vertex := routing.NewVertex(peer) vertex := routing.NewVertex(peer)
syncer, ok := d.peerSyncers[vertex]
syncer, ok := d.peerSyncers[routing.NewVertex(peer)]
if !ok { if !ok {
return return
} }