core/state/snapshot: fix data race in layer flattening (#23628)
* core/state/snapshot: fix data race in layer flattening * core/state/snapshot: fix typo
This commit is contained in:
@ -163,6 +163,9 @@ type Tree struct {
|
||||
cache int // Megabytes permitted to use for read caches
|
||||
layers map[common.Hash]snapshot // Collection of all known layers
|
||||
lock sync.RWMutex
|
||||
|
||||
// Test hooks
|
||||
onFlatten func() // Hook invoked when the bottom most diff layers are flattened
|
||||
}
|
||||
|
||||
// New attempts to load an already existing snapshot from a persistent key-value
|
||||
@ -463,14 +466,21 @@ func (t *Tree) cap(diff *diffLayer, layers int) *diskLayer {
|
||||
return nil
|
||||
|
||||
case *diffLayer:
|
||||
// Hold the write lock until the flattened parent is linked correctly.
|
||||
// Otherwise, the stale layer may be accessed by external reads in the
|
||||
// meantime.
|
||||
diff.lock.Lock()
|
||||
defer diff.lock.Unlock()
|
||||
|
||||
// Flatten the parent into the grandparent. The flattening internally obtains a
|
||||
// write lock on grandparent.
|
||||
flattened := parent.flatten().(*diffLayer)
|
||||
t.layers[flattened.root] = flattened
|
||||
|
||||
diff.lock.Lock()
|
||||
defer diff.lock.Unlock()
|
||||
|
||||
// Invoke the hook if it's registered. Ugly hack.
|
||||
if t.onFlatten != nil {
|
||||
t.onFlatten()
|
||||
}
|
||||
diff.parent = flattened
|
||||
if flattened.memory < aggregatorMemoryLimit {
|
||||
// Accumulator layer is smaller than the limit, so we can abort, unless
|
||||
|
Reference in New Issue
Block a user