forked from cerc-io/plugeth
core/state/snapshot: fix race condition (#24685)
Fixes three race conditions found through fuzzing by David Theodore
This commit is contained in:
parent
345b1fb827
commit
86d5477079
@ -258,6 +258,9 @@ func (dl *diffLayer) Root() common.Hash {
|
|||||||
|
|
||||||
// Parent returns the subsequent layer of a diff layer.
|
// Parent returns the subsequent layer of a diff layer.
|
||||||
func (dl *diffLayer) Parent() snapshot {
|
func (dl *diffLayer) Parent() snapshot {
|
||||||
|
dl.lock.RLock()
|
||||||
|
defer dl.lock.RUnlock()
|
||||||
|
|
||||||
return dl.parent
|
return dl.parent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -422,6 +422,8 @@ type Syncer struct {
|
|||||||
storageSynced uint64 // Number of storage slots downloaded
|
storageSynced uint64 // Number of storage slots downloaded
|
||||||
storageBytes common.StorageSize // Number of storage trie bytes persisted to disk
|
storageBytes common.StorageSize // Number of storage trie bytes persisted to disk
|
||||||
|
|
||||||
|
extProgress *SyncProgress // progress that can be exposed to external caller.
|
||||||
|
|
||||||
// Request tracking during healing phase
|
// Request tracking during healing phase
|
||||||
trienodeHealIdlers map[string]struct{} // Peers that aren't serving trie node requests
|
trienodeHealIdlers map[string]struct{} // Peers that aren't serving trie node requests
|
||||||
bytecodeHealIdlers map[string]struct{} // Peers that aren't serving bytecode requests
|
bytecodeHealIdlers map[string]struct{} // Peers that aren't serving bytecode requests
|
||||||
@ -477,6 +479,8 @@ func NewSyncer(db ethdb.KeyValueStore) *Syncer {
|
|||||||
trienodeHealReqs: make(map[uint64]*trienodeHealRequest),
|
trienodeHealReqs: make(map[uint64]*trienodeHealRequest),
|
||||||
bytecodeHealReqs: make(map[uint64]*bytecodeHealRequest),
|
bytecodeHealReqs: make(map[uint64]*bytecodeHealRequest),
|
||||||
stateWriter: db.NewBatch(),
|
stateWriter: db.NewBatch(),
|
||||||
|
|
||||||
|
extProgress: new(SyncProgress),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -633,6 +637,21 @@ func (s *Syncer) Sync(root common.Hash, cancel chan struct{}) error {
|
|||||||
s.assignTrienodeHealTasks(trienodeHealResps, trienodeHealReqFails, cancel)
|
s.assignTrienodeHealTasks(trienodeHealResps, trienodeHealReqFails, cancel)
|
||||||
s.assignBytecodeHealTasks(bytecodeHealResps, bytecodeHealReqFails, cancel)
|
s.assignBytecodeHealTasks(bytecodeHealResps, bytecodeHealReqFails, cancel)
|
||||||
}
|
}
|
||||||
|
// Update sync progress
|
||||||
|
s.lock.Lock()
|
||||||
|
s.extProgress = &SyncProgress{
|
||||||
|
AccountSynced: s.accountSynced,
|
||||||
|
AccountBytes: s.accountBytes,
|
||||||
|
BytecodeSynced: s.bytecodeSynced,
|
||||||
|
BytecodeBytes: s.bytecodeBytes,
|
||||||
|
StorageSynced: s.storageSynced,
|
||||||
|
StorageBytes: s.storageBytes,
|
||||||
|
TrienodeHealSynced: s.trienodeHealSynced,
|
||||||
|
TrienodeHealBytes: s.trienodeHealBytes,
|
||||||
|
BytecodeHealSynced: s.bytecodeHealSynced,
|
||||||
|
BytecodeHealBytes: s.bytecodeHealBytes,
|
||||||
|
}
|
||||||
|
s.lock.Unlock()
|
||||||
// Wait for something to happen
|
// Wait for something to happen
|
||||||
select {
|
select {
|
||||||
case <-s.update:
|
case <-s.update:
|
||||||
@ -705,6 +724,9 @@ func (s *Syncer) loadSyncStatus() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
s.lock.Lock()
|
||||||
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
s.snapped = len(s.tasks) == 0
|
s.snapped = len(s.tasks) == 0
|
||||||
|
|
||||||
s.accountSynced = progress.AccountSynced
|
s.accountSynced = progress.AccountSynced
|
||||||
@ -802,25 +824,12 @@ func (s *Syncer) saveSyncStatus() {
|
|||||||
func (s *Syncer) Progress() (*SyncProgress, *SyncPending) {
|
func (s *Syncer) Progress() (*SyncProgress, *SyncPending) {
|
||||||
s.lock.Lock()
|
s.lock.Lock()
|
||||||
defer s.lock.Unlock()
|
defer s.lock.Unlock()
|
||||||
|
|
||||||
progress := &SyncProgress{
|
|
||||||
AccountSynced: s.accountSynced,
|
|
||||||
AccountBytes: s.accountBytes,
|
|
||||||
BytecodeSynced: s.bytecodeSynced,
|
|
||||||
BytecodeBytes: s.bytecodeBytes,
|
|
||||||
StorageSynced: s.storageSynced,
|
|
||||||
StorageBytes: s.storageBytes,
|
|
||||||
TrienodeHealSynced: s.trienodeHealSynced,
|
|
||||||
TrienodeHealBytes: s.trienodeHealBytes,
|
|
||||||
BytecodeHealSynced: s.bytecodeHealSynced,
|
|
||||||
BytecodeHealBytes: s.bytecodeHealBytes,
|
|
||||||
}
|
|
||||||
pending := new(SyncPending)
|
pending := new(SyncPending)
|
||||||
if s.healer != nil {
|
if s.healer != nil {
|
||||||
pending.TrienodeHeal = uint64(len(s.healer.trieTasks))
|
pending.TrienodeHeal = uint64(len(s.healer.trieTasks))
|
||||||
pending.BytecodeHeal = uint64(len(s.healer.codeTasks))
|
pending.BytecodeHeal = uint64(len(s.healer.codeTasks))
|
||||||
}
|
}
|
||||||
return progress, pending
|
return s.extProgress, pending
|
||||||
}
|
}
|
||||||
|
|
||||||
// cleanAccountTasks removes account range retrieval tasks that have already been
|
// cleanAccountTasks removes account range retrieval tasks that have already been
|
||||||
|
Loading…
Reference in New Issue
Block a user