core/state: add some termination checks to prefetcher async shutdowns

This commit is contained in:
Péter Szilágyi 2024-05-09 11:02:17 +03:00
parent e9b599c6a1
commit 8d9f5eee3f

View file

@ -95,6 +95,8 @@ func (p *triePrefetcher) report() {
return return
} }
for _, fetcher := range p.fetchers { for _, fetcher := range p.fetchers {
fetcher.wait() // ensure the fetcher's idle before poking in its internals
if fetcher.root == p.root { if fetcher.root == p.root {
p.accountLoadMeter.Mark(int64(len(fetcher.seen))) p.accountLoadMeter.Mark(int64(len(fetcher.seen)))
p.accountDupMeter.Mark(int64(fetcher.dups)) p.accountDupMeter.Mark(int64(fetcher.dups))
@ -159,6 +161,7 @@ func (p *triePrefetcher) trie(owner common.Hash, root common.Hash) (Trie, error)
// how useful or wasteful the fetcher is. // how useful or wasteful the fetcher is.
func (p *triePrefetcher) used(owner common.Hash, root common.Hash, used [][]byte) { func (p *triePrefetcher) used(owner common.Hash, root common.Hash, used [][]byte) {
if fetcher := p.fetchers[p.trieID(owner, root)]; fetcher != nil { if fetcher := p.fetchers[p.trieID(owner, root)]; fetcher != nil {
fetcher.wait() // ensure the fetcher's idle before poking in its internals
fetcher.used = used fetcher.used = used
} }
} }
@ -236,13 +239,19 @@ func (sf *subfetcher) schedule(keys [][]byte) error {
return nil return nil
} }
// wait blocks until the subfetcher terminates. This method is used to block on
// an async termination before accessing internal fields from the fetcher.
func (sf *subfetcher) wait() {
<-sf.term
}
// peek retrieves the fetcher's trie, populated with any pre-fetched data. The // peek retrieves the fetcher's trie, populated with any pre-fetched data. The
// returned trie will be a shallow copy, so modifying it will break subsequent // returned trie will be a shallow copy, so modifying it will break subsequent
// peeks for the original data. The method will block until all the scheduled // peeks for the original data. The method will block until all the scheduled
// data has been loaded and the fethcer terminated. // data has been loaded and the fethcer terminated.
func (sf *subfetcher) peek() Trie { func (sf *subfetcher) peek() Trie {
// Block until the fertcher terminates, then retrieve the trie // Block until the fertcher terminates, then retrieve the trie
<-sf.term sf.wait()
return sf.trie return sf.trie
} }