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

blockchain: Avoid deadlock with additional locking #156

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions blockchain/accept.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,11 @@ func (b *BlockChain) maybeAcceptBlock(block *btcutil.Block, flags BehaviorFlags)
// Notify the caller that the new block was accepted into the block
// chain. The caller would typically want to react by relaying the
// inventory to other peers.
b.notificationLock.Lock()
b.chainLock.Unlock()
b.sendNotification(NTBlockAccepted, block)
b.chainLock.Lock()
b.notificationLock.Unlock()

return isMainChain, nil
}
17 changes: 12 additions & 5 deletions blockchain/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,9 @@ type BlockChain struct {
//
// In addition, some of the fields are stored in the database so the
// chain state can be quickly reconstructed on load.
stateLock sync.RWMutex
stateSnapshot *BestState
stateLock sync.RWMutex
stateSnapshot *BestState
notificationLock sync.Mutex

// The following caches are used to efficiently keep track of the
// current deployment threshold state of each rule change deployment.
Expand Down Expand Up @@ -685,9 +686,11 @@ func (b *BlockChain) connectBlock(node *blockNode, block *btcutil.Block,
// Notify the caller that the block was connected to the main chain.
// The caller would typically want to react with actions such as
// updating wallets.
b.notificationLock.Lock()
b.chainLock.Unlock()
b.sendNotification(NTBlockConnected, block)
b.chainLock.Lock()
b.notificationLock.Unlock()

return nil
}
Expand Down Expand Up @@ -810,9 +813,13 @@ func (b *BlockChain) disconnectBlock(node *blockNode, block *btcutil.Block, view
// Notify the caller that the block was disconnected from the main
// chain. The caller would typically want to react with actions such as
// updating wallets.
b.notificationLock.Lock()
b.chainLock.Unlock()
b.sendNotification(NTBlockDisconnected, block)
b.chainLock.Lock()
b.notificationLock.Unlock()
b.stateLock.Lock()
defer b.stateLock.Unlock()

return nil
}
Expand Down Expand Up @@ -1124,8 +1131,8 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla
// most common case.
parentHash := &block.MsgBlock().Header.PrevBlock
if parentHash.IsEqual(&b.bestChain.Tip().hash) {
// We're going to get the election state from either checkConnectBlock or
// in the case of fastAdd, from electionProcessBlock() directly
// We're going to get the election state from either checkConnectBlock
// or, in the case of fastAdd, from electionProcessBlock() directly
var nextEs *ElectionState

// Skip checks if node has already been fully validated.
Expand Down Expand Up @@ -1230,7 +1237,7 @@ func (b *BlockChain) connectBestChain(node *blockNode, block *btcutil.Block, fla
// find the common ancestor of both sides of the fork, disconnect the
// blocks that form the (now) old fork from the main chain, and attach
// the blocks that form the new chain to the main chain starting at the
// common ancenstor (the point where the chain forked).
// common ancestor (the point where the chain forked).
detachNodes, attachNodes := b.getReorganizeNodes(node)

// Reorganize the chain.
Expand Down