consensus: fix potential system deadlock
There is a notification pushed into the channel when block is being added, that notification is read by special goroutine that then forwards it to all subscribers to that particular event. Consensus goroutine is one of that subscribers, so for the system to properly function it has to read these events, but at the same time it can generate new blocks inside, so in some cases it can generate two blocks without ever reading from the subscription channel and this will lead to a deadlock. To avoid that we need to check subscription channel for events on every loop.
This commit is contained in:
parent
1dc93216ee
commit
af6a6f5f30
1 changed files with 18 additions and 7 deletions
|
@ -228,14 +228,25 @@ func (s *service) eventLoop() {
|
|||
case tx := <-s.transactions:
|
||||
s.dbft.OnTransaction(tx)
|
||||
case b := <-s.blockEvents:
|
||||
// We also receive our own blocks here, so check for index.
|
||||
if b.Index >= s.dbft.BlockIndex {
|
||||
s.log.Debug("new block in the chain",
|
||||
zap.Uint32("dbft index", s.dbft.BlockIndex),
|
||||
zap.Uint32("chain index", s.Chain.BlockHeight()))
|
||||
s.dbft.InitializeConsensus(0)
|
||||
}
|
||||
s.handleChainBlock(b)
|
||||
}
|
||||
// Always process block event if there is any, we can add one above.
|
||||
select {
|
||||
case b := <-s.blockEvents:
|
||||
s.handleChainBlock(b)
|
||||
default:
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) handleChainBlock(b *coreb.Block) {
|
||||
// We can get our own block here, so check for index.
|
||||
if b.Index >= s.dbft.BlockIndex {
|
||||
s.log.Debug("new block in the chain",
|
||||
zap.Uint32("dbft index", s.dbft.BlockIndex),
|
||||
zap.Uint32("chain index", s.Chain.BlockHeight()))
|
||||
s.dbft.InitializeConsensus(0)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue