light: fix disableCheckFreq locking (#18515)

This change unbreaks the build and removes racy access to
disableCheckFreq. Even though the field is set while holding
the lock, it was read outside of the protected section.
This commit is contained in:
Felix Lange 2019-01-24 13:40:37 +01:00 committed by GitHub
parent 0a454554ae
commit 684facedb8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -35,7 +35,7 @@ import (
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rlp"
"github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
) )
var ( var (
@ -50,6 +50,7 @@ type LightChain struct {
hc *core.HeaderChain hc *core.HeaderChain
indexerConfig *IndexerConfig indexerConfig *IndexerConfig
chainDb ethdb.Database chainDb ethdb.Database
engine consensus.Engine
odr OdrBackend odr OdrBackend
chainFeed event.Feed chainFeed event.Feed
chainSideFeed event.Feed chainSideFeed event.Feed
@ -57,21 +58,18 @@ type LightChain struct {
scope event.SubscriptionScope scope event.SubscriptionScope
genesisBlock *types.Block genesisBlock *types.Block
chainmu sync.RWMutex
bodyCache *lru.Cache // Cache for the most recent block bodies bodyCache *lru.Cache // Cache for the most recent block bodies
bodyRLPCache *lru.Cache // Cache for the most recent block bodies in RLP encoded format bodyRLPCache *lru.Cache // Cache for the most recent block bodies in RLP encoded format
blockCache *lru.Cache // Cache for the most recent entire blocks blockCache *lru.Cache // Cache for the most recent entire blocks
chainmu sync.RWMutex // protects header inserts
quit chan struct{} quit chan struct{}
running int32 // running must be called automically
// procInterrupt must be atomically called
procInterrupt int32 // interrupt signaler for block processing
wg sync.WaitGroup wg sync.WaitGroup
engine consensus.Engine // Atomic boolean switches:
running int32 // whether LightChain is running or stopped
disableCheckFreq bool procInterrupt int32 // interrupts chain insert
disableCheckFreq int32 // disables header verification
} }
// NewLightChain returns a fully initialised light chain using information // NewLightChain returns a fully initialised light chain using information
@ -356,7 +354,7 @@ func (self *LightChain) postChainEvents(events []interface{}) {
// In the case of a light chain, InsertHeaderChain also creates and posts light // In the case of a light chain, InsertHeaderChain also creates and posts light
// chain events when necessary. // chain events when necessary.
func (self *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) { func (self *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error) {
if self.disableCheckFreq { if atomic.LoadInt32(&self.disableCheckFreq) == 1 {
checkFreq = 0 checkFreq = 0
} }
start := time.Now() start := time.Now()
@ -532,16 +530,12 @@ func (self *LightChain) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEven
return self.scope.Track(new(event.Feed).Subscribe(ch)) return self.scope.Track(new(event.Feed).Subscribe(ch))
} }
//DisableCheckFreq disables header validation. It needs for ULC // DisableCheckFreq disables header validation. This is used for ultralight mode.
func (self *LightChain) DisableCheckFreq() { func (self *LightChain) DisableCheckFreq() {
self.mu.Lock() atomic.StoreInt32(&self.disableCheckFreq, 1)
defer self.mu.Unlock()
self.disableCheckFreq = true
} }
//EnableCheckFreq enables header validation // EnableCheckFreq enables header validation.
func (self *LightChain) EnableCheckFreq() { func (self *LightChain) EnableCheckFreq() {
self.mu.Lock() atomic.StoreInt32(&self.disableCheckFreq, 0)
defer self.mu.Unlock()
self.disableCheckFreq = false
} }