소스 검색

Merge pull request #1220 from karalabe/fix-chain-deadlock2

core: fix a lock annoyance and potential deadlock
Jeffrey Wilcke 10 년 전
부모
커밋
5950755b12
2개의 변경된 파일18개의 추가작업 그리고 6개의 파일을 삭제
  1. 12 5
      core/chain_manager.go
  2. 6 1
      event/filter/filter_test.go

+ 12 - 5
core/chain_manager.go

@@ -179,7 +179,9 @@ func (self *ChainManager) Td() *big.Int {
 }
 
 func (self *ChainManager) GasLimit() *big.Int {
-	// return self.currentGasLimit
+	self.mu.RLock()
+	defer self.mu.RUnlock()
+
 	return self.currentBlock.GasLimit()
 }
 
@@ -376,6 +378,8 @@ func (self *ChainManager) ExportN(w io.Writer, first uint64, last uint64) error
 	return nil
 }
 
+// insert injects a block into the current chain block chain. Note, this function
+// assumes that the `mu` mutex is held!
 func (bc *ChainManager) insert(block *types.Block) {
 	key := append(blockNumPre, block.Number().Bytes()...)
 	bc.blockDb.Put(key, block.Hash().Bytes())
@@ -484,6 +488,8 @@ func (self *ChainManager) GetAncestors(block *types.Block, length int) (blocks [
 	return
 }
 
+// setTotalDifficulty updates the TD of the chain manager. Note, this function
+// assumes that the `mu` mutex is held!
 func (bc *ChainManager) setTotalDifficulty(td *big.Int) {
 	bc.td = new(big.Int).Set(td)
 }
@@ -540,9 +546,6 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
 	self.wg.Add(1)
 	defer self.wg.Done()
 
-	self.mu.Lock()
-	defer self.mu.Unlock()
-
 	self.chainmu.Lock()
 	defer self.chainmu.Unlock()
 
@@ -625,7 +628,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
 		cblock := self.currentBlock
 		// Compare the TD of the last known block in the canonical chain to make sure it's greater.
 		// At this point it's possible that a different chain (fork) becomes the new canonical chain.
-		if block.Td.Cmp(self.td) > 0 {
+		if block.Td.Cmp(self.Td()) > 0 {
 			// chain fork
 			if block.ParentHash() != cblock.Hash() {
 				// during split we merge two different chains and create the new canonical chain
@@ -638,8 +641,10 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
 				queueEvent.splitCount++
 			}
 
+			self.mu.Lock()
 			self.setTotalDifficulty(block.Td)
 			self.insert(block)
+			self.mu.Unlock()
 
 			jsonlogger.LogJson(&logger.EthChainNewHead{
 				BlockHash:     block.Hash().Hex(),
@@ -747,9 +752,11 @@ func (self *ChainManager) merge(oldBlock, newBlock *types.Block) error {
 	}
 
 	// insert blocks. Order does not matter. Last block will be written in ImportChain itself which creates the new head properly
+	self.mu.Lock()
 	for _, block := range newChain {
 		self.insert(block)
 	}
+	self.mu.Unlock()
 
 	return nil
 }

+ 6 - 1
event/filter/filter_test.go

@@ -1,6 +1,9 @@
 package filter
 
-import "testing"
+import (
+	"testing"
+	"time"
+)
 
 func TestFilters(t *testing.T) {
 	var success bool
@@ -24,6 +27,8 @@ func TestFilters(t *testing.T) {
 	fm.Notify(Generic{Str1: "hello"}, true)
 	fm.Stop()
 
+	time.Sleep(10 * time.Millisecond) // yield to the notifier
+
 	if !success {
 		t.Error("expected 'hello' to be posted")
 	}