From ff0f3c50e9dcf2cc31caad995193301b515e37f2 Mon Sep 17 00:00:00 2001 From: jsvisa Date: Wed, 18 Jun 2025 23:16:02 +0800 Subject: [PATCH 1/3] core: fast exit if inserting stopped Signed-off-by: jsvisa --- core/blockchain.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/core/blockchain.go b/core/blockchain.go index 553be35e5364..8bb43aa1896b 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1914,6 +1914,11 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s ) defer interrupt.Store(true) // terminate the prefetch at the end + // Check for termination before starting block processing + if bc.insertStopped() { + return nil, errInsertionInterrupted + } + if bc.cacheConfig.TrieCleanNoPrefetch { statedb, err = state.New(parentRoot, bc.statedb) if err != nil { @@ -1981,6 +1986,11 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s }() } + // Check for termination before starting transaction processing + if bc.insertStopped() { + return nil, errInsertionInterrupted + } + // Process block using the parent state as reference point pstart := time.Now() res, err := bc.processor.Process(block, statedb, bc.vmConfig) @@ -1990,6 +2000,11 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s } ptime := time.Since(pstart) + // Check for termination before validation + if bc.insertStopped() { + return nil, errInsertionInterrupted + } + vstart := time.Now() if err := bc.validator.ValidateState(block, statedb, res, false); err != nil { bc.reportBlock(block, res, err) @@ -2046,6 +2061,11 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s blockValidationTimer.Update(vtime - (triehash + trieUpdate)) // The time spent on block validation blockCrossValidationTimer.Update(xvtime) // The time spent on stateless cross validation + // Check for termination before writing to database + if bc.insertStopped() { + return nil, errInsertionInterrupted + } + // Write the block to the chain and get the status. var ( wstart = time.Now() From 538ea2dea140428692afaa34183d19321d811727 Mon Sep 17 00:00:00 2001 From: jsvisa Date: Wed, 18 Jun 2025 23:16:19 +0800 Subject: [PATCH 2/3] eth: stop insert if terminate invoked Signed-off-by: jsvisa --- eth/downloader/downloader.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go index 762fb9283ea0..8f8f21959727 100644 --- a/eth/downloader/downloader.go +++ b/eth/downloader/downloader.go @@ -199,6 +199,9 @@ type BlockChain interface { // InsertChain inserts a batch of blocks into the local chain. InsertChain(types.Blocks) (int, error) + // StopInsert interrupts the inserting process. + StopInsert() + // InsertReceiptChain inserts a batch of blocks along with their receipts // into the local chain. Blocks older than the specified `ancientLimit` // are stored directly in the ancient store, while newer blocks are stored @@ -634,6 +637,9 @@ func (d *Downloader) Cancel() { // Terminate interrupts the downloader, canceling all pending operations. // The downloader cannot be reused after calling Terminate. func (d *Downloader) Terminate() { + // Signal to stop inserting in-flight blocks + d.blockchain.StopInsert() + // Close the termination channel (make sure double close is allowed) d.quitLock.Lock() select { From d58a973c5d9460ab73661a2145e19519a0d2d356 Mon Sep 17 00:00:00 2001 From: Gary Rong Date: Thu, 19 Jun 2025 09:08:17 +0800 Subject: [PATCH 3/3] core: remove duplicated interruption checks --- core/blockchain.go | 27 ++------------------------- 1 file changed, 2 insertions(+), 25 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index 8bb43aa1896b..27945130251e 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -278,9 +278,8 @@ type BlockChain struct { txLookupLock sync.RWMutex txLookupCache *lru.Cache[common.Hash, txLookup] - quit chan struct{} // shutdown signal, closed in Stop. - stopping atomic.Bool // false if chain is running, true when stopped - procInterrupt atomic.Bool // interrupt signaler for block processing + stopping atomic.Bool // false if chain is running, true when stopped + procInterrupt atomic.Bool // interrupt signaler for block processing engine consensus.Engine validator Validator // Block and state validator interface @@ -328,7 +327,6 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis db: db, triedb: triedb, triegc: prque.New[int64, common.Hash](nil), - quit: make(chan struct{}), chainmu: syncx.NewClosableMutex(), bodyCache: lru.NewCache[common.Hash, *types.Body](bodyCacheLimit), bodyRLPCache: lru.NewCache[common.Hash, rlp.RawValue](bodyCacheLimit), @@ -1206,7 +1204,6 @@ func (bc *BlockChain) stopWithoutSaving() { bc.scope.Close() // Signal shutdown to all goroutines. - close(bc.quit) bc.StopInsert() // Now wait for all chain modifications to end and persistent goroutines to exit. @@ -1914,11 +1911,6 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s ) defer interrupt.Store(true) // terminate the prefetch at the end - // Check for termination before starting block processing - if bc.insertStopped() { - return nil, errInsertionInterrupted - } - if bc.cacheConfig.TrieCleanNoPrefetch { statedb, err = state.New(parentRoot, bc.statedb) if err != nil { @@ -1986,11 +1978,6 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s }() } - // Check for termination before starting transaction processing - if bc.insertStopped() { - return nil, errInsertionInterrupted - } - // Process block using the parent state as reference point pstart := time.Now() res, err := bc.processor.Process(block, statedb, bc.vmConfig) @@ -2000,11 +1987,6 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s } ptime := time.Since(pstart) - // Check for termination before validation - if bc.insertStopped() { - return nil, errInsertionInterrupted - } - vstart := time.Now() if err := bc.validator.ValidateState(block, statedb, res, false); err != nil { bc.reportBlock(block, res, err) @@ -2061,11 +2043,6 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s blockValidationTimer.Update(vtime - (triehash + trieUpdate)) // The time spent on block validation blockCrossValidationTimer.Update(xvtime) // The time spent on stateless cross validation - // Check for termination before writing to database - if bc.insertStopped() { - return nil, errInsertionInterrupted - } - // Write the block to the chain and get the status. var ( wstart = time.Now()