eth/downloader: abort sync if master drops (timeout prev)

This commit is contained in:
Péter Szilágyi 2016-07-26 13:07:12 +03:00
parent a724952f75
commit 8f0a4a25f8

View File

@ -147,8 +147,10 @@ type Downloader struct {
stateWakeCh chan bool // [eth/63] Channel to signal the state fetcher of new tasks stateWakeCh chan bool // [eth/63] Channel to signal the state fetcher of new tasks
headerProcCh chan []*types.Header // [eth/62] Channel to feed the header processor new tasks headerProcCh chan []*types.Header // [eth/62] Channel to feed the header processor new tasks
// Cancellation and termination
cancelPeer string // Identifier of the peer currently being used as the master (cancel on drop)
cancelCh chan struct{} // Channel to cancel mid-flight syncs cancelCh chan struct{} // Channel to cancel mid-flight syncs
cancelLock sync.RWMutex // Lock to protect the cancel channel in delivers cancelLock sync.RWMutex // Lock to protect the cancel channel and peer in delivers
quitCh chan struct{} // Quit channel to signal termination quitCh chan struct{} // Quit channel to signal termination
quitLock sync.RWMutex // Lock to prevent double closes quitLock sync.RWMutex // Lock to prevent double closes
@ -254,12 +256,22 @@ func (d *Downloader) RegisterPeer(id string, version int, head common.Hash,
// the specified peer. An effort is also made to return any pending fetches into // the specified peer. An effort is also made to return any pending fetches into
// the queue. // the queue.
func (d *Downloader) UnregisterPeer(id string) error { func (d *Downloader) UnregisterPeer(id string) error {
// Unregister the peer from the active peer set and revoke any fetch tasks
glog.V(logger.Detail).Infoln("Unregistering peer", id) glog.V(logger.Detail).Infoln("Unregistering peer", id)
if err := d.peers.Unregister(id); err != nil { if err := d.peers.Unregister(id); err != nil {
glog.V(logger.Error).Infoln("Unregister failed:", err) glog.V(logger.Error).Infoln("Unregister failed:", err)
return err return err
} }
d.queue.Revoke(id) d.queue.Revoke(id)
// If this peer was the master peer, abort sync immediately
d.cancelLock.RLock()
master := id == d.cancelPeer
d.cancelLock.RUnlock()
if master {
d.cancel()
}
return nil return nil
} }
@ -332,9 +344,10 @@ func (d *Downloader) synchronise(id string, hash common.Hash, td *big.Int, mode
empty = true empty = true
} }
} }
// Create cancel channel for aborting mid-flight // Create cancel channel for aborting mid-flight and mark the master peer
d.cancelLock.Lock() d.cancelLock.Lock()
d.cancelCh = make(chan struct{}) d.cancelCh = make(chan struct{})
d.cancelPeer = id
d.cancelLock.Unlock() d.cancelLock.Unlock()
defer d.cancel() // No matter what, we can't leave the cancel channel open defer d.cancel() // No matter what, we can't leave the cancel channel open