mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-19 11:20:45 +00:00
core/state: prevent build goroutine leak when SizeTracker is stopped
SizeTracker.build delivers its result on an unbuffered channel. If the tracker is stopped while the initial measurement is running, init returns via the abort arm without receiving, and the build goroutine blocks forever on the send, regardless of whether the measurement failed or completed. Make both send sites select on the abort channel so the goroutine always terminates.
This commit is contained in:
parent
e5c5e1897d
commit
3b8082a10c
1 changed files with 12 additions and 2 deletions
|
|
@ -538,7 +538,12 @@ func (t *SizeTracker) build(root common.Hash, blockNumber uint64, done chan buil
|
|||
|
||||
// Wait for all goroutines to complete
|
||||
if err := group.Wait(); err != nil {
|
||||
done <- buildResult{err: err}
|
||||
select {
|
||||
case done <- buildResult{err: err}:
|
||||
case <-t.abort:
|
||||
// The tracker was closed and the receiver in init has
|
||||
// already exited, the result is no longer consumed.
|
||||
}
|
||||
} else {
|
||||
stat := SizeStats{
|
||||
StateRoot: root,
|
||||
|
|
@ -554,11 +559,16 @@ func (t *SizeTracker) build(root common.Hash, blockNumber uint64, done chan buil
|
|||
ContractCodes: codes,
|
||||
ContractCodeBytes: codeBytes,
|
||||
}
|
||||
done <- buildResult{
|
||||
select {
|
||||
case done <- buildResult{
|
||||
root: root,
|
||||
blockNumber: blockNumber,
|
||||
stat: stat,
|
||||
elapsed: time.Since(start),
|
||||
}:
|
||||
case <-t.abort:
|
||||
// The tracker was closed and the receiver in init has
|
||||
// already exited, the result is no longer consumed.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue