From 15b621f0f399afa12631e607964b6a64c371cd0b Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Sat, 19 Sep 2020 21:49:05 +0300 Subject: [PATCH] consensus: wait goroutine to finish on Shutdown Fixes: panic: assignment to entry in nil map goroutine 227 [running]: github.com/nspcc-dev/neo-go/pkg/core/storage.(*MemoryStore).put(...) /home/rik/dev/neo-go/pkg/core/storage/memory_store.go:53 github.com/nspcc-dev/neo-go/pkg/core/storage.(*MemoryStore).PutBatch(0xc00035f580, 0x110a680, 0xc000336750, 0x0, 0x0) /home/rik/dev/neo-go/pkg/core/storage/memory_store.go:93 +0x286 github.com/nspcc-dev/neo-go/pkg/core.(*Blockchain).addHeaders(0xc0000a2340, 0xc0001be301, 0xc00036d428, 0x1, 0x1, 0x0, 0x0) /home/rik/dev/neo-go/pkg/core/blockchain.go:516 +0xd5a github.com/nspcc-dev/neo-go/pkg/core.(*Blockchain).AddBlock(0xc0000a2340, 0xc0000bc2c0, 0x0, 0x0) /home/rik/dev/neo-go/pkg/core/blockchain.go:407 +0x9ca github.com/nspcc-dev/neo-go/pkg/consensus.(*service).processBlock(0xc000152160, 0x1122320, 0xc0000bc2c0) /home/rik/dev/neo-go/pkg/consensus/consensus.go:440 +0xbf github.com/nspcc-dev/dbft.(*DBFT).checkCommit(0xc0000d3400) /home/rik/go/pkg/mod/github.com/nspcc-dev/dbft@v0.0.0-20200911152629-be965ee4d449/check.go:71 +0x918 github.com/nspcc-dev/dbft.(*DBFT).checkPrepare(0xc0000d3400) /home/rik/go/pkg/mod/github.com/nspcc-dev/dbft@v0.0.0-20200911152629-be965ee4d449/check.go:36 +0x465 github.com/nspcc-dev/dbft.(*DBFT).sendPrepareRequest(0xc0000d3400) /home/rik/go/pkg/mod/github.com/nspcc-dev/dbft@v0.0.0-20200911152629-be965ee4d449/send.go:42 +0x2f8 github.com/nspcc-dev/dbft.(*DBFT).start(0xc0000d3400) /home/rik/go/pkg/mod/github.com/nspcc-dev/dbft@v0.0.0-20200911152629-be965ee4d449/dbft.go:269 +0x26f github.com/nspcc-dev/dbft.(*DBFT).Start(0xc0000d3400) /home/rik/go/pkg/mod/github.com/nspcc-dev/dbft@v0.0.0-20200911152629-be965ee4d449/dbft.go:82 +0x59 github.com/nspcc-dev/neo-go/pkg/consensus.(*service).Start(0xc000152160) /home/rik/dev/neo-go/pkg/consensus/consensus.go:191 +0x56 github.com/nspcc-dev/neo-go/pkg/network.(*Server).tryStartConsensus(0xc000235040) /home/rik/dev/neo-go/pkg/network/server.go:311 +0xda github.com/nspcc-dev/neo-go/pkg/network.(*Server).Start(0xc000235040, 0xc0000faba0) /home/rik/dev/neo-go/pkg/network/server.go:173 +0x202 created by github.com/nspcc-dev/neo-go/cli.newTestChain /home/rik/dev/neo-go/cli/executor_test.go:77 +0x47d FAIL github.com/nspcc-dev/neo-go/cli 14.479s --- pkg/consensus/consensus.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pkg/consensus/consensus.go b/pkg/consensus/consensus.go index 05cfd780d..1909397e4 100644 --- a/pkg/consensus/consensus.go +++ b/pkg/consensus/consensus.go @@ -74,8 +74,9 @@ type service struct { network netmode.Magic // started is a flag set with Start method that runs an event handling // goroutine. - started *atomic.Bool - quit chan struct{} + started *atomic.Bool + quit chan struct{} + finished chan struct{} } // Config is a configuration for consensus services. @@ -119,6 +120,7 @@ func NewService(cfg Config) (Service, error) { network: cfg.Chain.GetConfig().Magic, started: atomic.NewBool(false), quit: make(chan struct{}), + finished: make(chan struct{}), } if cfg.Wallet == nil { @@ -197,14 +199,16 @@ func (s *service) Start() { // Shutdown implements Service interface. func (s *service) Shutdown() { close(s.quit) + <-s.finished } func (s *service) eventLoop() { +events: for { select { case <-s.quit: s.dbft.Timer.Stop() - return + break events case <-s.dbft.Timer.C(): hv := s.dbft.Timer.HV() s.log.Debug("timer fired", @@ -250,6 +254,7 @@ func (s *service) eventLoop() { } } + close(s.finished) } func (s *service) handleChainBlock(b *coreb.Block) {