mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-07 21:44:27 +00:00
Merge pull request #842 from gzliudan/fix_downloader
eth/downloader: fix 2 bugs
This commit is contained in:
commit
47543e8b1c
1 changed files with 18 additions and 11 deletions
|
|
@ -140,9 +140,10 @@ type Downloader struct {
|
||||||
stateCh chan dataPack // [eth/63] Channel receiving inbound node state data
|
stateCh chan dataPack // [eth/63] Channel receiving inbound node state data
|
||||||
|
|
||||||
// Cancellation and termination
|
// Cancellation and termination
|
||||||
cancelPeer string // Identifier of the peer currently being used as the master (cancel on drop)
|
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 and peer in delivers
|
cancelLock sync.RWMutex // Lock to protect the cancel channel and peer in delivers
|
||||||
|
cancelWg sync.WaitGroup // Make sure all fetcher goroutines have exited.
|
||||||
|
|
||||||
quitCh chan struct{} // Quit channel to signal termination
|
quitCh chan struct{} // Quit channel to signal termination
|
||||||
quitLock sync.Mutex // Lock to prevent double closes
|
quitLock sync.Mutex // Lock to prevent double closes
|
||||||
|
|
@ -312,7 +313,7 @@ func (d *Downloader) UnregisterPeer(id string) error {
|
||||||
d.cancelLock.RUnlock()
|
d.cancelLock.RUnlock()
|
||||||
|
|
||||||
if master {
|
if master {
|
||||||
d.Cancel()
|
d.cancel()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -483,12 +484,11 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I
|
||||||
// spawnSync runs d.process and all given fetcher functions to completion in
|
// spawnSync runs d.process and all given fetcher functions to completion in
|
||||||
// separate goroutines, returning the first error that appears.
|
// separate goroutines, returning the first error that appears.
|
||||||
func (d *Downloader) spawnSync(fetchers []func() error) error {
|
func (d *Downloader) spawnSync(fetchers []func() error) error {
|
||||||
var wg sync.WaitGroup
|
|
||||||
errc := make(chan error, len(fetchers))
|
errc := make(chan error, len(fetchers))
|
||||||
wg.Add(len(fetchers))
|
d.cancelWg.Add(len(fetchers))
|
||||||
for _, fn := range fetchers {
|
for _, fn := range fetchers {
|
||||||
fn := fn
|
fn := fn
|
||||||
go func() { defer wg.Done(); errc <- fn() }()
|
go func() { defer d.cancelWg.Done(); errc <- fn() }()
|
||||||
}
|
}
|
||||||
// Wait for the first error, then terminate the others.
|
// Wait for the first error, then terminate the others.
|
||||||
var err error
|
var err error
|
||||||
|
|
@ -505,16 +505,16 @@ func (d *Downloader) spawnSync(fetchers []func() error) error {
|
||||||
}
|
}
|
||||||
d.queue.Close()
|
d.queue.Close()
|
||||||
d.Cancel()
|
d.Cancel()
|
||||||
wg.Wait()
|
|
||||||
if err == errEnoughBlock {
|
if err == errEnoughBlock {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cancel cancels all of the operations and resets the queue. It returns true
|
// cancel aborts all of the operations and resets the queue. However, cancel does
|
||||||
// if the cancel operation was completed.
|
// not wait for the running download goroutines to finish. This method should be
|
||||||
func (d *Downloader) Cancel() {
|
// used when cancelling the downloads from inside the downloader.
|
||||||
|
func (d *Downloader) cancel() {
|
||||||
// Close the current cancel channel
|
// Close the current cancel channel
|
||||||
d.cancelLock.Lock()
|
d.cancelLock.Lock()
|
||||||
if d.cancelCh != nil {
|
if d.cancelCh != nil {
|
||||||
|
|
@ -528,6 +528,13 @@ func (d *Downloader) Cancel() {
|
||||||
d.cancelLock.Unlock()
|
d.cancelLock.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cancel aborts all of the operations and waits for all download goroutines to
|
||||||
|
// finish before returning.
|
||||||
|
func (d *Downloader) Cancel() {
|
||||||
|
d.cancel()
|
||||||
|
d.cancelWg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
// Terminate interrupts the downloader, canceling all pending operations.
|
// Terminate interrupts the downloader, canceling all pending operations.
|
||||||
// The downloader cannot be reused after calling Terminate.
|
// The downloader cannot be reused after calling Terminate.
|
||||||
func (d *Downloader) Terminate() {
|
func (d *Downloader) Terminate() {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue