aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgary rong <garyrong0905@gmail.com>2018-04-16 16:37:48 +0800
committerPéter Szilágyi <peterke@gmail.com>2018-04-16 16:37:48 +0800
commitde2a7bb764c82dbaa80d37939c5862358174bc6e (patch)
treee2faf0ad5f342da3409f9d4cd64cdd08d451b11c
parent6b2b328cdb51a99e2ce55f0bc22eeb9733c9ec30 (diff)
downloaddexon-de2a7bb764c82dbaa80d37939c5862358174bc6e.tar
dexon-de2a7bb764c82dbaa80d37939c5862358174bc6e.tar.gz
dexon-de2a7bb764c82dbaa80d37939c5862358174bc6e.tar.bz2
dexon-de2a7bb764c82dbaa80d37939c5862358174bc6e.tar.lz
dexon-de2a7bb764c82dbaa80d37939c5862358174bc6e.tar.xz
dexon-de2a7bb764c82dbaa80d37939c5862358174bc6e.tar.zst
dexon-de2a7bb764c82dbaa80d37939c5862358174bc6e.zip
eth/downloader: wait for all fetcher goroutines to exit before terminating (#16509)
-rw-r--r--eth/downloader/downloader.go17
1 files changed, 8 insertions, 9 deletions
diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go
index 9e4949899..8b181b8ad 100644
--- a/eth/downloader/downloader.go
+++ b/eth/downloader/downloader.go
@@ -135,9 +135,10 @@ type Downloader struct {
stateCh chan dataPack // [eth/63] Channel receiving inbound node state data
// 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
- cancelLock sync.RWMutex // Lock to protect the cancel channel and peer in delivers
+ cancelPeer string // Identifier of the peer currently being used as the master (cancel on drop)
+ cancelCh chan struct{} // Channel to cancel mid-flight syncs
+ 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
quitLock sync.RWMutex // Lock to prevent double closes
@@ -476,12 +477,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
// separate goroutines, returning the first error that appears.
func (d *Downloader) spawnSync(fetchers []func() error) error {
- var wg sync.WaitGroup
errc := make(chan error, len(fetchers))
- wg.Add(len(fetchers))
+ d.cancelWg.Add(len(fetchers))
for _, fn := range fetchers {
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.
var err error
@@ -498,12 +498,10 @@ func (d *Downloader) spawnSync(fetchers []func() error) error {
}
d.queue.Close()
d.Cancel()
- wg.Wait()
return err
}
-// Cancel cancels all of the operations and resets the queue. It returns true
-// if the cancel operation was completed.
+// Cancel cancels all of the operations and resets the queue.
func (d *Downloader) Cancel() {
// Close the current cancel channel
d.cancelLock.Lock()
@@ -516,6 +514,7 @@ func (d *Downloader) Cancel() {
}
}
d.cancelLock.Unlock()
+ d.cancelWg.Wait()
}
// Terminate interrupts the downloader, canceling all pending operations.