-
Couldn't load subscription status.
- Fork 21.5k
core/state/snapshot: fix race condition #24685
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
Changes from all commits
ea16199
8aaca0c
16d8d70
6d4f686
da5dc9c
08f4188
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -422,6 +422,8 @@ type Syncer struct { | |
| storageSynced uint64 // Number of storage slots downloaded | ||
| 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 | ||
| trienodeHealIdlers map[string]struct{} // Peers that aren't serving trie node 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), | ||
| bytecodeHealReqs: make(map[uint64]*bytecodeHealRequest), | ||
| 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.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 | ||
| select { | ||
| case <-s.update: | ||
|
|
@@ -705,6 +724,9 @@ func (s *Syncer) loadSyncStatus() { | |
| } | ||
| } | ||
| } | ||
| s.lock.Lock() | ||
| defer s.lock.Unlock() | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This won't fix the issue unfortunately. These fields below are updated throughout the snap sync process locklessly. They were meant to be modified only by the syner loop and not accessed from the outside. Adding a lock everywhere will become super brittle. Trying to figure out what the best approach would be.. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copy it out onto a second one (intended for external exposure) every once in a while, and use locks on that one? |
||
|
|
||
| s.snapped = len(s.tasks) == 0 | ||
|
|
||
| s.accountSynced = progress.AccountSynced | ||
|
|
@@ -802,25 +824,12 @@ func (s *Syncer) saveSyncStatus() { | |
| func (s *Syncer) Progress() (*SyncProgress, *SyncPending) { | ||
| s.lock.Lock() | ||
| 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) | ||
| if s.healer != nil { | ||
| pending.TrienodeHeal = uint64(len(s.healer.trieTasks)) | ||
| pending.BytecodeHeal = uint64(len(s.healer.codeTasks)) | ||
| } | ||
| return progress, pending | ||
| return s.extProgress, pending | ||
| } | ||
|
|
||
| // cleanAccountTasks removes account range retrieval tasks that have already been | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.