Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eth: close miner on exit (instead of just stopping) #21992

Merged
merged 3 commits into from Oct 8, 2021

Conversation

holiman
Copy link
Contributor

@holiman holiman commented Dec 10, 2020

This PR fixes #19965, I think.

Previously, when shutting down the Ethereum service, the miner was stopped before the blockchain, which is fine. However, Stop and Close are diferent:

func (miner *Miner) Stop() {
	miner.stopCh <- struct{}{}
}

func (miner *Miner) Close() {
	close(miner.exitCh)
}

The Stop tells the worker routine to stop, but stays in the loop. The Close causes the miner to also shut down the worker routine, and then exit the main loop:

		case <-miner.stopCh:
			shouldStart = false
			miner.worker.stop()
		case <-miner.exitCh:
			miner.worker.close()
			return

In the worker, it's also different:

// stop sets the running status as 0.
func (w *worker) stop() {
	atomic.StoreInt32(&w.running, 0)
}

// close terminates all background threads maintained by the worker.
// Note the worker does not support being closed multiple times.
func (w *worker) close() {
	atomic.StoreInt32(&w.running, 0)
	close(w.exitCh)
}

They both set w.running to 0, but close also signals on the exitCh, which causes the worker loop to exit, and thus not do any more commit operations.
I'm fairly sure this change is for the better, however, I'm not 100% sure it solves the issue, since we're closing the worker.exitCh, but we don't actually wait for the worker to react to it -- so there's still a potential commit operation already happening.

If the issue still persist, we might do better by also adding a waitgroup to wait for the miner workers to actually exit before allowing the blockchain to shut down.

@rjl493456442 rjl493456442 self-assigned this Dec 10, 2020
@fjl fjl changed the title eth/backend: close miner on exit (instead of just stopping) eth: close miner on exit (instead of just stopping) Dec 17, 2020
@ryanschneider
Copy link
Contributor

ryanschneider commented Mar 18, 2021

I would love to see this in master soon, we update our rinkeby signer bi-weekly and we hit this panic pretty much every time.

edit: I added more logs to #19965, hope they help

@holiman
Copy link
Contributor Author

holiman commented Mar 22, 2021

@rjl493456442 PTAL

@holiman
Copy link
Contributor Author

holiman commented Apr 27, 2021

ping @rjl493456442 PTAL

Copy link
Contributor

@fjl fjl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please also add a sync.WaitGroup in miner/miner.go to wait for the shutdown of the Miner.update goroutine when Miner.Close is called.

@holiman
Copy link
Contributor Author

holiman commented May 25, 2021

Please also add a sync.WaitGroup in miner/miner.go to wait for the shutdown of the Miner.update goroutine when Miner.Close is called.

Fixed, ptal. I have not tested it yet, let's see what the tests say first

@ethereum ethereum deleted a comment from samlavery May 25, 2021
@holiman
Copy link
Contributor Author

holiman commented May 26, 2021

I'll put this PR on one of our PoA signers

@holiman
Copy link
Contributor Author

holiman commented Sep 21, 2021

rebased

Comment on lines +230 to 233
worker.wg.Add(4)
go worker.mainLoop()
go worker.newWorkLoop(recommit)
go worker.resultLoop()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm suggesting an approach which I think makes managing the wg a bit easier, by keeping all the code contained in one place.

Suggested change
worker.wg.Add(4)
go worker.mainLoop()
go worker.newWorkLoop(recommit)
go worker.resultLoop()
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()
}()

@fjl fjl merged commit 28d30b5 into ethereum:master Oct 8, 2021
@fjl fjl added this to the 1.10.10 milestone Oct 8, 2021
sidhujag pushed a commit to syscoin/go-ethereum that referenced this pull request Oct 9, 2021
This ensures that all miner goroutines have exited before stopping the blockchain. 

Co-authored-by: Felix Lange <fjl@twurst.com>
viaweb3 added a commit to kcc-community/kcc that referenced this pull request Jun 28, 2022
eth: close miner on exit (instead of just stopping) (ethereum#21992)
yongjun925 pushed a commit to DODOEX/go-ethereum that referenced this pull request Dec 3, 2022
This ensures that all miner goroutines have exited before stopping the blockchain. 

Co-authored-by: Felix Lange <fjl@twurst.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

concurrent map access panic on rinkeby signer shutdown
6 participants