Skip to content

Commit

Permalink
chain: prevent deadlock while notifying RescanFinished for NeutrinoCl…
Browse files Browse the repository at this point in the history
…ient
  • Loading branch information
wpaulino authored and cpacia committed Aug 20, 2019
1 parent 46872e6 commit ccf5867
Showing 1 changed file with 16 additions and 4 deletions.
20 changes: 16 additions & 4 deletions chain/neutrino.go
Expand Up @@ -332,19 +332,20 @@ func (s *NeutrinoClient) Rescan(startHash *chainhash.Hash, addrs []bchutil.Addre
outPoints map[wire.OutPoint]bchutil.Address) error {

s.clientMtx.Lock()
defer s.clientMtx.Unlock()

s.CS.NotifyMempoolReceived(addrs)

if !s.started {
s.clientMtx.Unlock()
return fmt.Errorf("can't do a rescan when the chain client " +
"is not started")
}
if s.scanning {
// Restart the rescan by killing the existing rescan.
close(s.rescanQuit)
rescan := s.rescan
s.clientMtx.Unlock()
s.rescan.WaitForShutdown()
rescan.WaitForShutdown()
s.clientMtx.Lock()
s.rescan = nil
s.rescanErr = nil
Expand All @@ -355,6 +356,7 @@ func (s *NeutrinoClient) Rescan(startHash *chainhash.Hash, addrs []bchutil.Addre
s.lastProgressSent = false
s.lastFilteredBlockHeader = nil
s.isRescan = true
s.clientMtx.Unlock()

bestBlock, err := s.CS.BestBlock()
if err != nil {
Expand All @@ -370,7 +372,14 @@ func (s *NeutrinoClient) Rescan(startHash *chainhash.Hash, addrs []bchutil.Addre
// with state that indicates a "fresh" wallet, we'll send a
// notification indicating the rescan has "finished".
if header.BlockHash() == *startHash {
s.clientMtx.Lock()
s.finished = true
rescanQuit := s.rescanQuit
s.clientMtx.Unlock()

// Release the lock while dispatching the notification since
// it's possible for the notificationHandler to be waiting to
// acquire it before receiving the notification.
select {
case s.enqueueNotification <- &RescanFinished{
Hash: startHash,
Expand All @@ -379,7 +388,7 @@ func (s *NeutrinoClient) Rescan(startHash *chainhash.Hash, addrs []bchutil.Addre
}:
case <-s.quit:
return nil
case <-s.rescanQuit:
case <-rescanQuit:
return nil
}
}
Expand All @@ -388,6 +397,7 @@ func (s *NeutrinoClient) Rescan(startHash *chainhash.Hash, addrs []bchutil.Addre
for op, addr := range outPoints {
addrScript, err := txscript.PayToAddrScript(addr)
if err != nil {
return err
}

inputsToWatch = append(inputsToWatch, neutrino.InputWithScript{
Expand All @@ -396,6 +406,7 @@ func (s *NeutrinoClient) Rescan(startHash *chainhash.Hash, addrs []bchutil.Addre
})
}

s.clientMtx.Lock()
newRescan := neutrino.NewRescan(
&neutrino.RescanChainSource{
ChainService: s.CS,
Expand All @@ -413,6 +424,7 @@ func (s *NeutrinoClient) Rescan(startHash *chainhash.Hash, addrs []bchutil.Addre
)
s.rescan = newRescan
s.rescanErr = s.rescan.Start()
s.clientMtx.Unlock()

return nil
}
Expand Down

0 comments on commit ccf5867

Please sign in to comment.