Merge pull request #20204 from holiman/fix_downloader_race
eth/downloader: fix data race in downloader
This commit is contained in:
		@@ -1574,13 +1574,14 @@ func (d *Downloader) importBlockResults(results []*fetchResult) error {
 | 
				
			|||||||
func (d *Downloader) processFastSyncContent(latest *types.Header) error {
 | 
					func (d *Downloader) processFastSyncContent(latest *types.Header) error {
 | 
				
			||||||
	// Start syncing state of the reported head block. This should get us most of
 | 
						// Start syncing state of the reported head block. This should get us most of
 | 
				
			||||||
	// the state of the pivot block.
 | 
						// the state of the pivot block.
 | 
				
			||||||
	stateSync := d.syncState(latest.Root)
 | 
						sync := d.syncState(latest.Root)
 | 
				
			||||||
	defer stateSync.Cancel()
 | 
						defer sync.Cancel()
 | 
				
			||||||
	go func() {
 | 
						closeOnErr := func(s *stateSync) {
 | 
				
			||||||
		if err := stateSync.Wait(); err != nil && err != errCancelStateFetch && err != errCanceled {
 | 
							if err := s.Wait(); err != nil && err != errCancelStateFetch && err != errCanceled {
 | 
				
			||||||
			d.queue.Close() // wake up Results
 | 
								d.queue.Close() // wake up Results
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}()
 | 
						}
 | 
				
			||||||
 | 
						go closeOnErr(sync)
 | 
				
			||||||
	// Figure out the ideal pivot block. Note, that this goalpost may move if the
 | 
						// Figure out the ideal pivot block. Note, that this goalpost may move if the
 | 
				
			||||||
	// sync takes long enough for the chain head to move significantly.
 | 
						// sync takes long enough for the chain head to move significantly.
 | 
				
			||||||
	pivot := uint64(0)
 | 
						pivot := uint64(0)
 | 
				
			||||||
@@ -1600,12 +1601,12 @@ func (d *Downloader) processFastSyncContent(latest *types.Header) error {
 | 
				
			|||||||
		if len(results) == 0 {
 | 
							if len(results) == 0 {
 | 
				
			||||||
			// If pivot sync is done, stop
 | 
								// If pivot sync is done, stop
 | 
				
			||||||
			if oldPivot == nil {
 | 
								if oldPivot == nil {
 | 
				
			||||||
				return stateSync.Cancel()
 | 
									return sync.Cancel()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			// If sync failed, stop
 | 
								// If sync failed, stop
 | 
				
			||||||
			select {
 | 
								select {
 | 
				
			||||||
			case <-d.cancelCh:
 | 
								case <-d.cancelCh:
 | 
				
			||||||
				stateSync.Cancel()
 | 
									sync.Cancel()
 | 
				
			||||||
				return errCanceled
 | 
									return errCanceled
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -1625,28 +1626,24 @@ func (d *Downloader) processFastSyncContent(latest *types.Header) error {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		P, beforeP, afterP := splitAroundPivot(pivot, results)
 | 
							P, beforeP, afterP := splitAroundPivot(pivot, results)
 | 
				
			||||||
		if err := d.commitFastSyncData(beforeP, stateSync); err != nil {
 | 
							if err := d.commitFastSyncData(beforeP, sync); err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if P != nil {
 | 
							if P != nil {
 | 
				
			||||||
			// If new pivot block found, cancel old state retrieval and restart
 | 
								// If new pivot block found, cancel old state retrieval and restart
 | 
				
			||||||
			if oldPivot != P {
 | 
								if oldPivot != P {
 | 
				
			||||||
				stateSync.Cancel()
 | 
									sync.Cancel()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				stateSync = d.syncState(P.Header.Root)
 | 
									sync = d.syncState(P.Header.Root)
 | 
				
			||||||
				defer stateSync.Cancel()
 | 
									defer sync.Cancel()
 | 
				
			||||||
				go func() {
 | 
									go closeOnErr(sync)
 | 
				
			||||||
					if err := stateSync.Wait(); err != nil && err != errCancelStateFetch && err != errCanceled {
 | 
					 | 
				
			||||||
						d.queue.Close() // wake up Results
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}()
 | 
					 | 
				
			||||||
				oldPivot = P
 | 
									oldPivot = P
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			// Wait for completion, occasionally checking for pivot staleness
 | 
								// Wait for completion, occasionally checking for pivot staleness
 | 
				
			||||||
			select {
 | 
								select {
 | 
				
			||||||
			case <-stateSync.done:
 | 
								case <-sync.done:
 | 
				
			||||||
				if stateSync.err != nil {
 | 
									if sync.err != nil {
 | 
				
			||||||
					return stateSync.err
 | 
										return sync.err
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if err := d.commitPivotBlock(P); err != nil {
 | 
									if err := d.commitPivotBlock(P); err != nil {
 | 
				
			||||||
					return err
 | 
										return err
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user