Skip to content

Commit 78b6059

Browse files
jsvisarjl493456442
andauthored
eth: quick canceling block inserting when debug_setHead is invoked (#32067)
If Geth is engaged in a long-run block synchronization, such as a full syncing over a large number of blocks, invoking `debug_setHead` will cause `downloader.Cancel` to wait for all fetchers to stop first. This can be time-consuming, particularly for the block processing thread. To address this, we manually call `blockchain.StopInsert` to interrupt the blocking processing thread and allow it to exit immediately, and after that call `blockchain.ResumeInsert` to resume the block downloading process. Additionally, we add a sanity check for the input block number of `debug_setHead` to ensure its validity. --------- Signed-off-by: jsvisa <[email protected]> Co-authored-by: Gary Rong <[email protected]>
1 parent 2192020 commit 78b6059

File tree

3 files changed

+23
-12
lines changed

3 files changed

+23
-12
lines changed

core/blockchain.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,7 +1244,7 @@ func (bc *BlockChain) stopWithoutSaving() {
12441244
bc.scope.Close()
12451245

12461246
// Signal shutdown to all goroutines.
1247-
bc.StopInsert()
1247+
bc.InterruptInsert(true)
12481248

12491249
// Now wait for all chain modifications to end and persistent goroutines to exit.
12501250
//
@@ -1318,11 +1318,15 @@ func (bc *BlockChain) Stop() {
13181318
log.Info("Blockchain stopped")
13191319
}
13201320

1321-
// StopInsert interrupts all insertion methods, causing them to return
1322-
// errInsertionInterrupted as soon as possible. Insertion is permanently disabled after
1323-
// calling this method.
1324-
func (bc *BlockChain) StopInsert() {
1325-
bc.procInterrupt.Store(true)
1321+
// InterruptInsert interrupts all insertion methods, causing them to return
1322+
// errInsertionInterrupted as soon as possible, or resume the chain insertion
1323+
// if required.
1324+
func (bc *BlockChain) InterruptInsert(on bool) {
1325+
if on {
1326+
bc.procInterrupt.Store(true)
1327+
} else {
1328+
bc.procInterrupt.Store(false)
1329+
}
13261330
}
13271331

13281332
// insertStopped returns true after StopInsert has been called.

eth/downloader/downloader.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,8 @@ type BlockChain interface {
199199
// InsertChain inserts a batch of blocks into the local chain.
200200
InsertChain(types.Blocks) (int, error)
201201

202-
// StopInsert interrupts the inserting process.
203-
StopInsert()
202+
// InterruptInsert whether disables the chain insertion.
203+
InterruptInsert(on bool)
204204

205205
// InsertReceiptChain inserts a batch of blocks along with their receipts
206206
// into the local chain. Blocks older than the specified `ancientLimit`
@@ -630,16 +630,15 @@ func (d *Downloader) cancel() {
630630
// Cancel aborts all of the operations and waits for all download goroutines to
631631
// finish before returning.
632632
func (d *Downloader) Cancel() {
633+
d.blockchain.InterruptInsert(true)
633634
d.cancel()
634635
d.cancelWg.Wait()
636+
d.blockchain.InterruptInsert(false)
635637
}
636638

637639
// Terminate interrupts the downloader, canceling all pending operations.
638640
// The downloader cannot be reused after calling Terminate.
639641
func (d *Downloader) Terminate() {
640-
// Signal to stop inserting in-flight blocks
641-
d.blockchain.StopInsert()
642-
643642
// Close the termination channel (make sure double close is allowed)
644643
d.quitLock.Lock()
645644
select {

internal/ethapi/api.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1831,8 +1831,16 @@ func (api *DebugAPI) ChaindbCompact() error {
18311831
}
18321832

18331833
// SetHead rewinds the head of the blockchain to a previous block.
1834-
func (api *DebugAPI) SetHead(number hexutil.Uint64) {
1834+
func (api *DebugAPI) SetHead(number hexutil.Uint64) error {
1835+
header := api.b.CurrentHeader()
1836+
if header == nil {
1837+
return errors.New("current header is not available")
1838+
}
1839+
if header.Number.Uint64() <= uint64(number) {
1840+
return errors.New("not allowed to rewind to a future block")
1841+
}
18351842
api.b.SetHead(uint64(number))
1843+
return nil
18361844
}
18371845

18381846
// NetAPI offers network related RPC methods

0 commit comments

Comments
 (0)