fix: use time.After in loop, possible memory leaks

This commit is contained in:
songzhibin97 2024-03-13 11:00:45 +08:00
parent 758fce71fa
commit 89f5aa6104
7 changed files with 53 additions and 14 deletions

View file

@ -596,6 +596,9 @@ func (s *MatcherSession) deliverSections(bit uint, sections []uint64, bitsets []
// of the session, any request in-flight need to be responded to! Empty responses // of the session, any request in-flight need to be responded to! Empty responses
// are fine though in that case. // are fine though in that case.
func (s *MatcherSession) Multiplex(batch int, wait time.Duration, mux chan chan *Retrieval) { func (s *MatcherSession) Multiplex(batch int, wait time.Duration, mux chan chan *Retrieval) {
waitTimer := time.NewTimer(wait)
defer waitTimer.Stop()
for { for {
// Allocate a new bloom bit index to retrieve data for, stopping when done // Allocate a new bloom bit index to retrieve data for, stopping when done
bit, ok := s.allocateRetrieval() bit, ok := s.allocateRetrieval()
@ -604,6 +607,7 @@ func (s *MatcherSession) Multiplex(batch int, wait time.Duration, mux chan chan
} }
// Bit allocated, throttle a bit if we're below our batch limit // Bit allocated, throttle a bit if we're below our batch limit
if s.pendingSections(bit) < batch { if s.pendingSections(bit) < batch {
waitTimer.Reset(wait)
select { select {
case <-s.quit: case <-s.quit:
// Session terminating, we can't meaningfully service, abort // Session terminating, we can't meaningfully service, abort
@ -611,7 +615,7 @@ func (s *MatcherSession) Multiplex(batch int, wait time.Duration, mux chan chan
s.deliverSections(bit, []uint64{}, [][]byte{}) s.deliverSections(bit, []uint64{}, [][]byte{})
return return
case <-time.After(wait): case <-waitTimer.C:
// Throttling up, fetch whatever is available // Throttling up, fetch whatever is available
} }
} }

View file

@ -289,6 +289,10 @@ func (d *Downloader) fetchBeaconHeaders(from uint64) error {
localHeaders = d.readHeaderRange(tail, int(count)) localHeaders = d.readHeaderRange(tail, int(count))
log.Warn("Retrieved beacon headers from local", "from", from, "count", count) log.Warn("Retrieved beacon headers from local", "from", from, "count", count)
} }
fsHeaderContCheckTimer := time.NewTimer(fsHeaderContCheck)
defer fsHeaderContCheckTimer.Stop()
for { for {
// Some beacon headers might have appeared since the last cycle, make // Some beacon headers might have appeared since the last cycle, make
// sure we're always syncing to all available ones // sure we're always syncing to all available ones
@ -381,8 +385,9 @@ func (d *Downloader) fetchBeaconHeaders(from uint64) error {
} }
// State sync still going, wait a bit for new headers and retry // State sync still going, wait a bit for new headers and retry
log.Trace("Pivot not yet committed, waiting...") log.Trace("Pivot not yet committed, waiting...")
fsHeaderContCheckTimer.Reset(fsHeaderContCheck)
select { select {
case <-time.After(fsHeaderContCheck): case <-fsHeaderContCheckTimer.C:
case <-d.cancelCh: case <-d.cancelCh:
return errCanceled return errCanceled
} }

View file

@ -1020,6 +1020,10 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, head uint64) e
ancestor = from ancestor = from
mode = d.getMode() mode = d.getMode()
) )
fsHeaderContCheckTimer := time.NewTimer(fsHeaderContCheck)
defer fsHeaderContCheckTimer.Stop()
for { for {
// Pull the next batch of headers, it either: // Pull the next batch of headers, it either:
// - Pivot check to see if the chain moved too far // - Pivot check to see if the chain moved too far
@ -1124,8 +1128,9 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, head uint64) e
// Don't abort header fetches while the pivot is downloading // Don't abort header fetches while the pivot is downloading
if !d.committed.Load() && pivot <= from { if !d.committed.Load() && pivot <= from {
p.log.Debug("No headers, waiting for pivot commit") p.log.Debug("No headers, waiting for pivot commit")
fsHeaderContCheckTimer.Reset(fsHeaderContCheck)
select { select {
case <-time.After(fsHeaderContCheck): case <-fsHeaderContCheckTimer.C:
continue continue
case <-d.cancelCh: case <-d.cancelCh:
return errCanceled return errCanceled
@ -1194,9 +1199,10 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, head uint64) e
// sleep a bit and retry. Take care with headers already consumed during // sleep a bit and retry. Take care with headers already consumed during
// skeleton filling // skeleton filling
if len(headers) == 0 && !progressed { if len(headers) == 0 && !progressed {
fsHeaderContCheckTimer.Reset(fsHeaderContCheck)
p.log.Trace("All headers delayed, waiting") p.log.Trace("All headers delayed, waiting")
select { select {
case <-time.After(fsHeaderContCheck): case <-fsHeaderContCheckTimer.C:
continue continue
case <-d.cancelCh: case <-d.cancelCh:
return errCanceled return errCanceled
@ -1274,9 +1280,13 @@ func (d *Downloader) fetchReceipts(from uint64, beaconMode bool) error {
// queue until the stream ends or a failure occurs. // queue until the stream ends or a failure occurs.
func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode bool) error { func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode bool) error {
var ( var (
mode = d.getMode() mode = d.getMode()
gotHeaders = false // Wait for batches of headers to process gotHeaders = false // Wait for batches of headers to process
secondTimer = time.NewTimer(time.Second)
) )
defer secondTimer.Stop()
for { for {
select { select {
case <-d.cancelCh: case <-d.cancelCh:
@ -1397,10 +1407,11 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode
if mode == FullSync || mode == SnapSync { if mode == FullSync || mode == SnapSync {
// If we've reached the allowed number of pending headers, stall a bit // If we've reached the allowed number of pending headers, stall a bit
for d.queue.PendingBodies() >= maxQueuedHeaders || d.queue.PendingReceipts() >= maxQueuedHeaders { for d.queue.PendingBodies() >= maxQueuedHeaders || d.queue.PendingReceipts() >= maxQueuedHeaders {
secondTimer.Reset(time.Second)
select { select {
case <-d.cancelCh: case <-d.cancelCh:
return errCanceled return errCanceled
case <-time.After(time.Second): case <-secondTimer.C:
} }
} }
// Otherwise insert the headers for content retrieval // Otherwise insert the headers for content retrieval
@ -1565,9 +1576,11 @@ func (d *Downloader) processSnapSyncContent() error {
// Note, there's no issue with memory piling up since after 64 blocks the // Note, there's no issue with memory piling up since after 64 blocks the
// pivot will forcefully move so these accumulators will be dropped. // pivot will forcefully move so these accumulators will be dropped.
var ( var (
oldPivot *fetchResult // Locked in pivot block, might change eventually oldPivot *fetchResult // Locked in pivot block, might change eventually
oldTail []*fetchResult // Downloaded content after the pivot oldTail []*fetchResult // Downloaded content after the pivot
secondTimer = time.NewTimer(time.Second)
) )
defer secondTimer.Stop()
for { for {
// Wait for the next batch of downloaded data to be available. If we have // Wait for the next batch of downloaded data to be available. If we have
// not yet reached the pivot point, wait blockingly as there's no need to // not yet reached the pivot point, wait blockingly as there's no need to
@ -1650,6 +1663,7 @@ func (d *Downloader) processSnapSyncContent() error {
oldPivot = P oldPivot = P
} }
// Wait for completion, occasionally checking for pivot staleness // Wait for completion, occasionally checking for pivot staleness
secondTimer.Reset(time.Second)
select { select {
case <-sync.done: case <-sync.done:
if sync.err != nil { if sync.err != nil {
@ -1660,7 +1674,7 @@ func (d *Downloader) processSnapSyncContent() error {
} }
oldPivot = nil oldPivot = nil
case <-time.After(time.Second): case <-secondTimer.C:
oldTail = afterP oldTail = afterP
continue continue
} }

View file

@ -544,10 +544,14 @@ func (s *Service) reportLatency(conn *connWrapper) error {
return err return err
} }
// Wait for the pong request to arrive back // Wait for the pong request to arrive back
timer := time.NewTimer(5 * time.Second)
defer timer.Stop()
select { select {
case <-s.pongCh: case <-s.pongCh:
// Pong delivered, report the latency // Pong delivered, report the latency
case <-time.After(5 * time.Second): case <-timer.C:
// Ping timeout, abort // Ping timeout, abort
return errors.New("ping timed out") return errors.New("ping timed out")
} }

View file

@ -303,10 +303,14 @@ func (n *ExecNode) Stop() error {
go func() { go func() {
waitErr <- n.Cmd.Wait() waitErr <- n.Cmd.Wait()
}() }()
timer := time.NewTimer(5 * time.Second)
defer timer.Stop()
select { select {
case err := <-waitErr: case err := <-waitErr:
return err return err
case <-time.After(5 * time.Second): case <-timer.C:
return n.Cmd.Process.Kill() return n.Cmd.Process.Kill()
} }
} }

View file

@ -67,6 +67,10 @@ func startStop(net *Network, quit chan struct{}, nodeCount int) {
} }
tick := time.NewTicker(10 * time.Second) tick := time.NewTicker(10 * time.Second)
defer tick.Stop() defer tick.Stop()
timer := time.NewTimer(3 * time.Second)
defer timer.Stop()
for { for {
select { select {
case <-quit: case <-quit:
@ -80,11 +84,12 @@ func startStop(net *Network, quit chan struct{}, nodeCount int) {
return return
} }
timer.Reset(3 * time.Second)
select { select {
case <-quit: case <-quit:
log.Info("Terminating simulation loop") log.Info("Terminating simulation loop")
return return
case <-time.After(3 * time.Second): case <-timer.C:
} }
log.Debug("starting node", "id", id) log.Debug("starting node", "id", id)

View file

@ -1028,11 +1028,14 @@ func (net *Network) Load(snap *Snapshot) error {
} }
} }
snapshotLoadTimeoutTimer := time.NewTimer(snapshotLoadTimeout)
defer snapshotLoadTimeoutTimer.Stop()
select { select {
// Wait until all connections from the snapshot are established. // Wait until all connections from the snapshot are established.
case <-allConnected: case <-allConnected:
// Make sure that we do not wait forever. // Make sure that we do not wait forever.
case <-time.After(snapshotLoadTimeout): case <-snapshotLoadTimeoutTimer.C:
return errors.New("snapshot connections not established") return errors.New("snapshot connections not established")
} }
return nil return nil