eth/downloader: fix statesync fast restart race, hang test

This commit is contained in:
Péter Szilágyi 2018-02-02 17:35:49 +02:00
parent 3c30b2851d
commit 5f253f61ba
No known key found for this signature in database
GPG key ID: E9AE538CEDF8293D
2 changed files with 12 additions and 5 deletions

View file

@ -1354,7 +1354,7 @@ func (d *Downloader) processFastSyncContent(latest *types.Header) error {
stateSync := d.syncState(latest.Root) stateSync := d.syncState(latest.Root)
defer stateSync.Cancel() defer stateSync.Cancel()
go func() { go func() {
if err := stateSync.Wait(); err != nil { if err := stateSync.Wait(); err != nil && err != errCancelStateFetch {
d.queue.Close() // wake up WaitResults d.queue.Close() // wake up WaitResults
} }
}() }()
@ -1412,7 +1412,7 @@ func (d *Downloader) processFastSyncContent(latest *types.Header) error {
stateSync = d.syncState(P.Header.Root) stateSync = d.syncState(P.Header.Root)
defer stateSync.Cancel() defer stateSync.Cancel()
go func() { go func() {
if err := stateSync.Wait(); err != nil { if err := stateSync.Wait(); err != nil && err != errCancelStateFetch {
d.queue.Close() // wake up WaitResults d.queue.Close() // wake up WaitResults
} }
}() }()

View file

@ -1688,6 +1688,7 @@ func TestDeliverHeadersHang(t *testing.T) {
type floodingTestPeer struct { type floodingTestPeer struct {
peer Peer peer Peer
tester *downloadTester tester *downloadTester
pend sync.WaitGroup
} }
func (ftp *floodingTestPeer) Head() (common.Hash, *big.Int) { return ftp.peer.Head() } func (ftp *floodingTestPeer) Head() (common.Hash, *big.Int) { return ftp.peer.Head() }
@ -1708,9 +1709,12 @@ func (ftp *floodingTestPeer) RequestHeadersByNumber(from uint64, count, skip int
deliveriesDone := make(chan struct{}, 500) deliveriesDone := make(chan struct{}, 500)
for i := 0; i < cap(deliveriesDone); i++ { for i := 0; i < cap(deliveriesDone); i++ {
peer := fmt.Sprintf("fake-peer%d", i) peer := fmt.Sprintf("fake-peer%d", i)
ftp.pend.Add(1)
go func() { go func() {
ftp.tester.downloader.DeliverHeaders(peer, []*types.Header{{}, {}, {}, {}}) ftp.tester.downloader.DeliverHeaders(peer, []*types.Header{{}, {}, {}, {}})
deliveriesDone <- struct{}{} deliveriesDone <- struct{}{}
ftp.pend.Done()
}() }()
} }
// Deliver the actual requested headers. // Deliver the actual requested headers.
@ -1742,12 +1746,15 @@ func testDeliverHeadersHang(t *testing.T, protocol int, mode SyncMode) {
// Whenever the downloader requests headers, flood it with // Whenever the downloader requests headers, flood it with
// a lot of unrequested header deliveries. // a lot of unrequested header deliveries.
tester.downloader.peers.peers["peer"].peer = &floodingTestPeer{ tester.downloader.peers.peers["peer"].peer = &floodingTestPeer{
tester.downloader.peers.peers["peer"].peer, peer: tester.downloader.peers.peers["peer"].peer,
tester, tester: tester,
} }
if err := tester.sync("peer", nil, mode); err != nil { if err := tester.sync("peer", nil, mode); err != nil {
t.Errorf("sync failed: %v", err) t.Errorf("test %d: sync failed: %v", i, err)
} }
tester.terminate() tester.terminate()
// Flush all goroutines to prevent messing with subsequent tests
tester.downloader.peers.peers["peer"].peer.(*floodingTestPeer).pend.Wait()
} }
} }