eth: fix data race accessing peer.recentHash
This commit is contained in:
		
							parent
							
								
									05cae69d72
								
							
						
					
					
						commit
						44147d057d
					
				| @ -157,7 +157,7 @@ func (pm *ProtocolManager) handle(p *peer) error { | |||||||
| 	} | 	} | ||||||
| 	defer pm.removePeer(p.id) | 	defer pm.removePeer(p.id) | ||||||
| 
 | 
 | ||||||
| 	if err := pm.downloader.RegisterPeer(p.id, p.recentHash, p.requestHashes, p.requestBlocks); err != nil { | 	if err := pm.downloader.RegisterPeer(p.id, p.Head(), p.requestHashes, p.requestBlocks); err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| 	// propagate existing transactions. new transactions appearing
 | 	// propagate existing transactions. new transactions appearing
 | ||||||
| @ -303,7 +303,7 @@ func (self *ProtocolManager) handleMsg(p *peer) error { | |||||||
| 		// Mark the hashes as present at the remote node
 | 		// Mark the hashes as present at the remote node
 | ||||||
| 		for _, hash := range hashes { | 		for _, hash := range hashes { | ||||||
| 			p.blockHashes.Add(hash) | 			p.blockHashes.Add(hash) | ||||||
| 			p.recentHash = hash | 			p.SetHead(hash) | ||||||
| 		} | 		} | ||||||
| 		// Schedule all the unknown hashes for retrieval
 | 		// Schedule all the unknown hashes for retrieval
 | ||||||
| 		unknown := make([]common.Hash, 0, len(hashes)) | 		unknown := make([]common.Hash, 0, len(hashes)) | ||||||
| @ -354,7 +354,7 @@ func (pm *ProtocolManager) importBlock(p *peer, block *types.Block, td *big.Int) | |||||||
| 
 | 
 | ||||||
| 	// Mark the block as present at the remote node (don't duplicate already held data)
 | 	// Mark the block as present at the remote node (don't duplicate already held data)
 | ||||||
| 	p.blockHashes.Add(hash) | 	p.blockHashes.Add(hash) | ||||||
| 	p.recentHash = hash | 	p.SetHead(hash) | ||||||
| 	if td != nil { | 	if td != nil { | ||||||
| 		p.td = td | 		p.td = td | ||||||
| 	} | 	} | ||||||
|  | |||||||
							
								
								
									
										31
									
								
								eth/peer.go
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								eth/peer.go
									
									
									
									
									
								
							| @ -40,9 +40,11 @@ type peer struct { | |||||||
| 
 | 
 | ||||||
| 	protv, netid int | 	protv, netid int | ||||||
| 
 | 
 | ||||||
| 	recentHash common.Hash | 	id string | ||||||
| 	id         string | 	td *big.Int | ||||||
| 	td         *big.Int | 
 | ||||||
|  | 	head     common.Hash | ||||||
|  | 	headLock sync.RWMutex | ||||||
| 
 | 
 | ||||||
| 	genesis, ourHash common.Hash | 	genesis, ourHash common.Hash | ||||||
| 	ourTd            *big.Int | 	ourTd            *big.Int | ||||||
| @ -51,14 +53,14 @@ type peer struct { | |||||||
| 	blockHashes *set.Set | 	blockHashes *set.Set | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func newPeer(protv, netid int, genesis, recentHash common.Hash, td *big.Int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { | func newPeer(protv, netid int, genesis, head common.Hash, td *big.Int, p *p2p.Peer, rw p2p.MsgReadWriter) *peer { | ||||||
| 	id := p.ID() | 	id := p.ID() | ||||||
| 
 | 
 | ||||||
| 	return &peer{ | 	return &peer{ | ||||||
| 		Peer:        p, | 		Peer:        p, | ||||||
| 		rw:          rw, | 		rw:          rw, | ||||||
| 		genesis:     genesis, | 		genesis:     genesis, | ||||||
| 		ourHash:     recentHash, | 		ourHash:     head, | ||||||
| 		ourTd:       td, | 		ourTd:       td, | ||||||
| 		protv:       protv, | 		protv:       protv, | ||||||
| 		netid:       netid, | 		netid:       netid, | ||||||
| @ -68,6 +70,23 @@ func newPeer(protv, netid int, genesis, recentHash common.Hash, td *big.Int, p * | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | // Head retrieves a copy of the current head (most recent) hash of the peer.
 | ||||||
|  | func (p *peer) Head() (hash common.Hash) { | ||||||
|  | 	p.headLock.RLock() | ||||||
|  | 	defer p.headLock.RUnlock() | ||||||
|  | 
 | ||||||
|  | 	copy(hash[:], p.head[:]) | ||||||
|  | 	return hash | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // SetHead updates the head (most recent) hash of the peer.
 | ||||||
|  | func (p *peer) SetHead(hash common.Hash) { | ||||||
|  | 	p.headLock.Lock() | ||||||
|  | 	defer p.headLock.Unlock() | ||||||
|  | 
 | ||||||
|  | 	copy(p.head[:], hash[:]) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // sendTransactions sends transactions to the peer and includes the hashes
 | // sendTransactions sends transactions to the peer and includes the hashes
 | ||||||
| // in it's tx hash set for future reference. The tx hash will allow the
 | // in it's tx hash set for future reference. The tx hash will allow the
 | ||||||
| // manager to check whether the peer has already received this particular
 | // manager to check whether the peer has already received this particular
 | ||||||
| @ -160,7 +179,7 @@ func (p *peer) handleStatus() error { | |||||||
| 	// Set the total difficulty of the peer
 | 	// Set the total difficulty of the peer
 | ||||||
| 	p.td = status.TD | 	p.td = status.TD | ||||||
| 	// set the best hash of the peer
 | 	// set the best hash of the peer
 | ||||||
| 	p.recentHash = status.CurrentBlock | 	p.head = status.CurrentBlock | ||||||
| 
 | 
 | ||||||
| 	return <-errc | 	return <-errc | ||||||
| } | } | ||||||
|  | |||||||
| @ -214,14 +214,15 @@ func (pm *ProtocolManager) synchronise(peer *peer) { | |||||||
| 	// FIXME if we have the hash in our chain and the TD of the peer is
 | 	// FIXME if we have the hash in our chain and the TD of the peer is
 | ||||||
| 	// much higher than ours, something is wrong with us or the peer.
 | 	// much higher than ours, something is wrong with us or the peer.
 | ||||||
| 	// Check if the hash is on our own chain
 | 	// Check if the hash is on our own chain
 | ||||||
| 	if pm.chainman.HasBlock(peer.recentHash) { | 	head := peer.Head() | ||||||
|  | 	if pm.chainman.HasBlock(head) { | ||||||
| 		glog.V(logger.Debug).Infoln("Synchronisation canceled: head already known") | 		glog.V(logger.Debug).Infoln("Synchronisation canceled: head already known") | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	// Get the hashes from the peer (synchronously)
 | 	// Get the hashes from the peer (synchronously)
 | ||||||
| 	glog.V(logger.Detail).Infof("Attempting synchronisation: %v, 0x%x", peer.id, peer.recentHash) | 	glog.V(logger.Detail).Infof("Attempting synchronisation: %v, 0x%x", peer.id, head) | ||||||
| 
 | 
 | ||||||
| 	err := pm.downloader.Synchronise(peer.id, peer.recentHash) | 	err := pm.downloader.Synchronise(peer.id, head) | ||||||
| 	switch err { | 	switch err { | ||||||
| 	case nil: | 	case nil: | ||||||
| 		glog.V(logger.Detail).Infof("Synchronisation completed") | 		glog.V(logger.Detail).Infof("Synchronisation completed") | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user