mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 14:46:42 +00:00
Address goroutine leak
This commit is contained in:
parent
f45da7ca0a
commit
d9daacad17
6 changed files with 24 additions and 46 deletions
|
|
@ -43,7 +43,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
"github.com/ethereum/go-ethereum/core/state/snapshot"
|
||||||
"github.com/ethereum/go-ethereum/core/stateless"
|
|
||||||
"github.com/ethereum/go-ethereum/core/tracing"
|
"github.com/ethereum/go-ethereum/core/tracing"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
|
|
@ -617,15 +616,7 @@ func (bc *BlockChain) ProcessBlock(block *types.Block, parent *types.Header) (_
|
||||||
processorCount++
|
processorCount++
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
// todo: @anshalshukla || @cffls - check witness collection and requirement in start prefetchers
|
parallelStatedb.StartPrefetcher("chain", nil)
|
||||||
var witness *stateless.Witness
|
|
||||||
if bc.vmConfig.EnableWitnessCollection {
|
|
||||||
witness, err = stateless.NewWitness(bc, block)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
parallelStatedb.StartPrefetcher("chain", witness)
|
|
||||||
receipts, logs, usedGas, err := bc.parallelProcessor.Process(block, parallelStatedb, bc.vmConfig, ctx)
|
receipts, logs, usedGas, err := bc.parallelProcessor.Process(block, parallelStatedb, bc.vmConfig, ctx)
|
||||||
resultChan <- Result{receipts, logs, usedGas, err, parallelStatedb, blockExecutionParallelCounter}
|
resultChan <- Result{receipts, logs, usedGas, err, parallelStatedb, blockExecutionParallelCounter}
|
||||||
}()
|
}()
|
||||||
|
|
@ -641,16 +632,7 @@ func (bc *BlockChain) ProcessBlock(block *types.Block, parent *types.Header) (_
|
||||||
processorCount++
|
processorCount++
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
// todo: @anshalshukla || @cffls - check witness collection and requirement in start prefetchers
|
statedb.StartPrefetcher("chain", nil)
|
||||||
var witness *stateless.Witness
|
|
||||||
if bc.vmConfig.EnableWitnessCollection {
|
|
||||||
witness, err = stateless.NewWitness(bc, block)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
statedb.StartPrefetcher("chain", witness)
|
|
||||||
|
|
||||||
receipts, logs, usedGas, err := bc.processor.Process(block, statedb, bc.vmConfig, ctx)
|
receipts, logs, usedGas, err := bc.processor.Process(block, statedb, bc.vmConfig, ctx)
|
||||||
resultChan <- Result{receipts, logs, usedGas, err, statedb, blockExecutionSerialCounter}
|
resultChan <- Result{receipts, logs, usedGas, err, statedb, blockExecutionSerialCounter}
|
||||||
}()
|
}()
|
||||||
|
|
@ -2319,27 +2301,6 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool) (int, error)
|
||||||
parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
|
parent = bc.GetHeader(block.ParentHash(), block.NumberU64()-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
statedb, err := state.New(parent.Root, bc.stateCache, bc.snaps)
|
|
||||||
if err != nil {
|
|
||||||
return it.index, err
|
|
||||||
}
|
|
||||||
statedb.SetLogger(bc.logger)
|
|
||||||
|
|
||||||
// If we are past Byzantium, enable prefetching to pull in trie node paths
|
|
||||||
// while processing transactions. Before Byzantium the prefetcher is mostly
|
|
||||||
// useless due to the intermediate root hashing after each transaction.
|
|
||||||
if bc.chainConfig.IsByzantium(block.Number()) {
|
|
||||||
var witness *stateless.Witness
|
|
||||||
if bc.vmConfig.EnableWitnessCollection {
|
|
||||||
witness, err = stateless.NewWitness(bc, block)
|
|
||||||
if err != nil {
|
|
||||||
return it.index, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
statedb.StartPrefetcher("chain", witness)
|
|
||||||
}
|
|
||||||
activeState = statedb
|
|
||||||
|
|
||||||
// If we have a followup block, run that against the current state to pre-cache
|
// If we have a followup block, run that against the current state to pre-cache
|
||||||
// transactions and probabilistically some of the account/storage trie nodes.
|
// transactions and probabilistically some of the account/storage trie nodes.
|
||||||
var followupInterrupt atomic.Bool
|
var followupInterrupt atomic.Bool
|
||||||
|
|
|
||||||
|
|
@ -363,8 +363,6 @@ func (p *ParallelStateProcessor) Process(block *types.Block, statedb *state.Stat
|
||||||
if task.shouldRerunWithoutFeeDelay {
|
if task.shouldRerunWithoutFeeDelay {
|
||||||
shouldDelayFeeCal = false
|
shouldDelayFeeCal = false
|
||||||
|
|
||||||
statedb.StopPrefetcher()
|
|
||||||
|
|
||||||
// nolint
|
// nolint
|
||||||
*statedb = *backupStateDB
|
*statedb = *backupStateDB
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1179,6 +1179,10 @@ func (s *StateDB) Copy() *StateDB {
|
||||||
state.accessList = s.accessList.Copy()
|
state.accessList = s.accessList.Copy()
|
||||||
state.transientStorage = s.transientStorage.Copy()
|
state.transientStorage = s.transientStorage.Copy()
|
||||||
|
|
||||||
|
if s.prefetcher != nil {
|
||||||
|
state.prefetcher = s.prefetcher
|
||||||
|
}
|
||||||
|
|
||||||
if s.mvHashmap != nil {
|
if s.mvHashmap != nil {
|
||||||
state.mvHashmap = s.mvHashmap
|
state.mvHashmap = s.mvHashmap
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,8 @@ type triePrefetcher struct {
|
||||||
storageDupWriteMeter metrics.Meter
|
storageDupWriteMeter metrics.Meter
|
||||||
storageDupCrossMeter metrics.Meter
|
storageDupCrossMeter metrics.Meter
|
||||||
storageWasteMeter metrics.Meter
|
storageWasteMeter metrics.Meter
|
||||||
|
|
||||||
|
lock sync.RWMutex // Use RWMutex for better read/write locking
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTriePrefetcher(db Database, root common.Hash, namespace string, noreads bool) *triePrefetcher {
|
func newTriePrefetcher(db Database, root common.Hash, namespace string, noreads bool) *triePrefetcher {
|
||||||
|
|
@ -94,6 +96,9 @@ func newTriePrefetcher(db Database, root common.Hash, namespace string, noreads
|
||||||
// to all of them. Depending on the async parameter, the method will either block
|
// to all of them. Depending on the async parameter, the method will either block
|
||||||
// until all subfetchers spin down, or return immediately.
|
// until all subfetchers spin down, or return immediately.
|
||||||
func (p *triePrefetcher) terminate(async bool) {
|
func (p *triePrefetcher) terminate(async bool) {
|
||||||
|
p.lock.Lock() // Lock for writing
|
||||||
|
defer p.lock.Unlock() // Ensure the lock is released after the function
|
||||||
|
|
||||||
// Short circuit if the fetcher is already closed
|
// Short circuit if the fetcher is already closed
|
||||||
select {
|
select {
|
||||||
case <-p.term:
|
case <-p.term:
|
||||||
|
|
@ -109,6 +114,9 @@ func (p *triePrefetcher) terminate(async bool) {
|
||||||
|
|
||||||
// report aggregates the pre-fetching and usage metrics and reports them.
|
// report aggregates the pre-fetching and usage metrics and reports them.
|
||||||
func (p *triePrefetcher) report() {
|
func (p *triePrefetcher) report() {
|
||||||
|
p.lock.RLock() // Lock for reading
|
||||||
|
defer p.lock.RUnlock() // Ensure the lock is released after the function
|
||||||
|
|
||||||
if !metrics.Enabled {
|
if !metrics.Enabled {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -157,6 +165,9 @@ func (p *triePrefetcher) report() {
|
||||||
// repeated.
|
// repeated.
|
||||||
// 2. Finalize of the main account trie. This happens only once per block.
|
// 2. Finalize of the main account trie. This happens only once per block.
|
||||||
func (p *triePrefetcher) prefetch(owner common.Hash, root common.Hash, addr common.Address, keys [][]byte, read bool) error {
|
func (p *triePrefetcher) prefetch(owner common.Hash, root common.Hash, addr common.Address, keys [][]byte, read bool) error {
|
||||||
|
p.lock.Lock() // Lock for writing
|
||||||
|
defer p.lock.Unlock() // Ensure the lock is released after the function
|
||||||
|
|
||||||
// If the state item is only being read, but reads are disabled, return
|
// If the state item is only being read, but reads are disabled, return
|
||||||
if read && p.noreads {
|
if read && p.noreads {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -181,6 +192,9 @@ func (p *triePrefetcher) prefetch(owner common.Hash, root common.Hash, addr comm
|
||||||
// the given trie terminates. If no fetcher exists for the request, nil will be
|
// the given trie terminates. If no fetcher exists for the request, nil will be
|
||||||
// returned.
|
// returned.
|
||||||
func (p *triePrefetcher) trie(owner common.Hash, root common.Hash) Trie {
|
func (p *triePrefetcher) trie(owner common.Hash, root common.Hash) Trie {
|
||||||
|
p.lock.RLock() // Lock for reading
|
||||||
|
defer p.lock.RUnlock() // Ensure the lock is released after the function
|
||||||
|
|
||||||
// Bail if no trie was prefetched for this root
|
// Bail if no trie was prefetched for this root
|
||||||
fetcher := p.fetchers[p.trieID(owner, root)]
|
fetcher := p.fetchers[p.trieID(owner, root)]
|
||||||
if fetcher == nil {
|
if fetcher == nil {
|
||||||
|
|
@ -195,6 +209,9 @@ func (p *triePrefetcher) trie(owner common.Hash, root common.Hash) Trie {
|
||||||
// used marks a batch of state items used to allow creating statistics as to
|
// used marks a batch of state items used to allow creating statistics as to
|
||||||
// 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) {
|
||||||
|
p.lock.Lock() // Lock for writing
|
||||||
|
defer p.lock.Unlock() // Ensure the lock is released after the function
|
||||||
|
|
||||||
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.wait() // ensure the fetcher's idle before poking in its internals
|
||||||
fetcher.used = used
|
fetcher.used = used
|
||||||
|
|
|
||||||
|
|
@ -525,8 +525,6 @@ func (h *handler) Start(maxPeers int) {
|
||||||
|
|
||||||
func (h *handler) Stop() {
|
func (h *handler) Stop() {
|
||||||
h.txsSub.Unsubscribe() // quits txBroadcastLoop
|
h.txsSub.Unsubscribe() // quits txBroadcastLoop
|
||||||
h.txFetcher.Stop()
|
|
||||||
h.downloader.Terminate()
|
|
||||||
h.minedBlockSub.Unsubscribe()
|
h.minedBlockSub.Unsubscribe()
|
||||||
|
|
||||||
// Quit chainSync and txsync64.
|
// Quit chainSync and txsync64.
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ func (cs *chainSyncer) loop() {
|
||||||
cs.handler.txFetcher.Start()
|
cs.handler.txFetcher.Start()
|
||||||
|
|
||||||
defer cs.handler.blockFetcher.Stop()
|
defer cs.handler.blockFetcher.Stop()
|
||||||
// defer cs.handler.txFetcher.Stop()
|
defer cs.handler.txFetcher.Stop()
|
||||||
defer cs.handler.downloader.Terminate()
|
defer cs.handler.downloader.Terminate()
|
||||||
|
|
||||||
// The force timer lowers the peer count threshold down to one when it fires.
|
// The force timer lowers the peer count threshold down to one when it fires.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue