From 082ec8fd541d195d36144d31edd148e29fe32846 Mon Sep 17 00:00:00 2001 From: Piers Powlesland Date: Fri, 1 Oct 2021 16:40:08 +0100 Subject: [PATCH] Ensure the miner is closed Also make miner and worker wait for goroutines to end at Shutdown. Without this change, when shutting down its possible for the worker to try and access the db after it has been closed, which results in a critical failure and runs the risk of corrupting the db. --- eth/backend.go | 1 + miner/miner.go | 4 +++- miner/worker.go | 23 +++++++++++++++++++---- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/eth/backend.go b/eth/backend.go index 793d3b81f1b1f..2672029cd9395 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -555,6 +555,7 @@ func (s *Ethereum) Stop() error { close(s.closeBloomHandler) s.txPool.Stop() s.miner.Stop() + s.miner.Close() s.blockchain.Stop() s.engine.Close() rawdb.PopUncleanShutdownMarker(s.chainDb) diff --git a/miner/miner.go b/miner/miner.go index a4a01b9f4ff70..f5c5fe85692b8 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -139,6 +139,7 @@ func (miner *Miner) update() { miner.worker.stop() case <-miner.exitCh: miner.worker.close() + miner.exitCh <- struct{}{} return } } @@ -153,7 +154,8 @@ func (miner *Miner) Stop() { } func (miner *Miner) Close() { - close(miner.exitCh) + miner.exitCh <- struct{}{} + <-miner.exitCh } func (miner *Miner) Mining() bool { diff --git a/miner/worker.go b/miner/worker.go index 8bdb1eff7ca02..d3b7580ab4c76 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -147,6 +147,7 @@ type worker struct { resultCh chan *types.Block startCh chan struct{} exitCh chan struct{} + wg sync.WaitGroup resubmitIntervalCh chan time.Duration resubmitAdjustCh chan *intervalAdjust @@ -225,10 +226,23 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus recommit = minRecommitInterval } - go worker.mainLoop() - go worker.newWorkLoop(recommit) - go worker.resultLoop() - go worker.taskLoop() + worker.wg.Add(4) + go func() { + defer worker.wg.Done() + worker.mainLoop() + }() + go func() { + defer worker.wg.Done() + worker.newWorkLoop(recommit) + }() + go func() { + defer worker.wg.Done() + worker.resultLoop() + }() + go func() { + defer worker.wg.Done() + worker.taskLoop() + }() // Submit first work to initialize pending state. if init { @@ -323,6 +337,7 @@ func (w *worker) close() { } atomic.StoreInt32(&w.running, 0) close(w.exitCh) + w.wg.Wait() } // recalcRecommit recalculates the resubmitting interval upon feedback.