Skip to content

Commit 47543e8

Browse files
authored
Merge pull request #842 from gzliudan/fix_downloader
eth/downloader: fix 2 bugs
2 parents 4602e23 + 652c66e commit 47543e8

File tree

1 file changed

+18
-11
lines changed

1 file changed

+18
-11
lines changed

eth/downloader/downloader.go

+18-11
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,10 @@ type Downloader struct {
140140
stateCh chan dataPack // [eth/63] Channel receiving inbound node state data
141141

142142
// Cancellation and termination
143-
cancelPeer string // Identifier of the peer currently being used as the master (cancel on drop)
144-
cancelCh chan struct{} // Channel to cancel mid-flight syncs
145-
cancelLock sync.RWMutex // Lock to protect the cancel channel and peer in delivers
143+
cancelPeer string // Identifier of the peer currently being used as the master (cancel on drop)
144+
cancelCh chan struct{} // Channel to cancel mid-flight syncs
145+
cancelLock sync.RWMutex // Lock to protect the cancel channel and peer in delivers
146+
cancelWg sync.WaitGroup // Make sure all fetcher goroutines have exited.
146147

147148
quitCh chan struct{} // Quit channel to signal termination
148149
quitLock sync.Mutex // Lock to prevent double closes
@@ -312,7 +313,7 @@ func (d *Downloader) UnregisterPeer(id string) error {
312313
d.cancelLock.RUnlock()
313314

314315
if master {
315-
d.Cancel()
316+
d.cancel()
316317
}
317318
return nil
318319
}
@@ -483,12 +484,11 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I
483484
// spawnSync runs d.process and all given fetcher functions to completion in
484485
// separate goroutines, returning the first error that appears.
485486
func (d *Downloader) spawnSync(fetchers []func() error) error {
486-
var wg sync.WaitGroup
487487
errc := make(chan error, len(fetchers))
488-
wg.Add(len(fetchers))
488+
d.cancelWg.Add(len(fetchers))
489489
for _, fn := range fetchers {
490490
fn := fn
491-
go func() { defer wg.Done(); errc <- fn() }()
491+
go func() { defer d.cancelWg.Done(); errc <- fn() }()
492492
}
493493
// Wait for the first error, then terminate the others.
494494
var err error
@@ -505,16 +505,16 @@ func (d *Downloader) spawnSync(fetchers []func() error) error {
505505
}
506506
d.queue.Close()
507507
d.Cancel()
508-
wg.Wait()
509508
if err == errEnoughBlock {
510509
return nil
511510
}
512511
return err
513512
}
514513

515-
// Cancel cancels all of the operations and resets the queue. It returns true
516-
// if the cancel operation was completed.
517-
func (d *Downloader) Cancel() {
514+
// cancel aborts all of the operations and resets the queue. However, cancel does
515+
// not wait for the running download goroutines to finish. This method should be
516+
// used when cancelling the downloads from inside the downloader.
517+
func (d *Downloader) cancel() {
518518
// Close the current cancel channel
519519
d.cancelLock.Lock()
520520
if d.cancelCh != nil {
@@ -528,6 +528,13 @@ func (d *Downloader) Cancel() {
528528
d.cancelLock.Unlock()
529529
}
530530

531+
// Cancel aborts all of the operations and waits for all download goroutines to
532+
// finish before returning.
533+
func (d *Downloader) Cancel() {
534+
d.cancel()
535+
d.cancelWg.Wait()
536+
}
537+
531538
// Terminate interrupts the downloader, canceling all pending operations.
532539
// The downloader cannot be reused after calling Terminate.
533540
func (d *Downloader) Terminate() {

0 commit comments

Comments
 (0)