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
// are fine though in that case.
func (s *MatcherSession) Multiplex(batch int, wait time.Duration, mux chan chan *Retrieval) {
waitTimer := time.NewTimer(wait)
defer waitTimer.Stop()
for {
// Allocate a new bloom bit index to retrieve data for, stopping when done
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
if s.pendingSections(bit) < batch {
waitTimer.Reset(wait)
select {
case <-s.quit:
// 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{})
return
case <-time.After(wait):
case <-waitTimer.C:
// 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))
log.Warn("Retrieved beacon headers from local", "from", from, "count", count)
}
fsHeaderContCheckTimer := time.NewTimer(fsHeaderContCheck)
defer fsHeaderContCheckTimer.Stop()
for {
// Some beacon headers might have appeared since the last cycle, make
// 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
log.Trace("Pivot not yet committed, waiting...")
fsHeaderContCheckTimer.Reset(fsHeaderContCheck)
select {
case <-time.After(fsHeaderContCheck):
case <-fsHeaderContCheckTimer.C:
case <-d.cancelCh:
return errCanceled
}

View file

@ -1020,6 +1020,10 @@ func (d *Downloader) fetchHeaders(p *peerConnection, from uint64, head uint64) e
ancestor = from
mode = d.getMode()
)
fsHeaderContCheckTimer := time.NewTimer(fsHeaderContCheck)
defer fsHeaderContCheckTimer.Stop()
for {
// Pull the next batch of headers, it either:
// - 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
if !d.committed.Load() && pivot <= from {
p.log.Debug("No headers, waiting for pivot commit")
fsHeaderContCheckTimer.Reset(fsHeaderContCheck)
select {
case <-time.After(fsHeaderContCheck):
case <-fsHeaderContCheckTimer.C:
continue
case <-d.cancelCh:
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
// skeleton filling
if len(headers) == 0 && !progressed {
fsHeaderContCheckTimer.Reset(fsHeaderContCheck)
p.log.Trace("All headers delayed, waiting")
select {
case <-time.After(fsHeaderContCheck):
case <-fsHeaderContCheckTimer.C:
continue
case <-d.cancelCh:
return errCanceled
@ -1274,9 +1280,13 @@ func (d *Downloader) fetchReceipts(from uint64, beaconMode bool) error {
// queue until the stream ends or a failure occurs.
func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode bool) error {
var (
mode = d.getMode()
gotHeaders = false // Wait for batches of headers to process
mode = d.getMode()
gotHeaders = false // Wait for batches of headers to process
secondTimer = time.NewTimer(time.Second)
)
defer secondTimer.Stop()
for {
select {
case <-d.cancelCh:
@ -1397,10 +1407,11 @@ func (d *Downloader) processHeaders(origin uint64, td, ttd *big.Int, beaconMode
if mode == FullSync || mode == SnapSync {
// If we've reached the allowed number of pending headers, stall a bit
for d.queue.PendingBodies() >= maxQueuedHeaders || d.queue.PendingReceipts() >= maxQueuedHeaders {
secondTimer.Reset(time.Second)
select {
case <-d.cancelCh:
return errCanceled
case <-time.After(time.Second):
case <-secondTimer.C:
}
}
// 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
// pivot will forcefully move so these accumulators will be dropped.
var (
oldPivot *fetchResult // Locked in pivot block, might change eventually
oldTail []*fetchResult // Downloaded content after the pivot
oldPivot *fetchResult // Locked in pivot block, might change eventually
oldTail []*fetchResult // Downloaded content after the pivot
secondTimer = time.NewTimer(time.Second)
)
defer secondTimer.Stop()
for {
// 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
@ -1650,6 +1663,7 @@ func (d *Downloader) processSnapSyncContent() error {
oldPivot = P
}
// Wait for completion, occasionally checking for pivot staleness
secondTimer.Reset(time.Second)
select {
case <-sync.done:
if sync.err != nil {
@ -1660,7 +1674,7 @@ func (d *Downloader) processSnapSyncContent() error {
}
oldPivot = nil
case <-time.After(time.Second):
case <-secondTimer.C:
oldTail = afterP
continue
}

View file

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

View file

@ -303,10 +303,14 @@ func (n *ExecNode) Stop() error {
go func() {
waitErr <- n.Cmd.Wait()
}()
timer := time.NewTimer(5 * time.Second)
defer timer.Stop()
select {
case err := <-waitErr:
return err
case <-time.After(5 * time.Second):
case <-timer.C:
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)
defer tick.Stop()
timer := time.NewTimer(3 * time.Second)
defer timer.Stop()
for {
select {
case <-quit:
@ -80,11 +84,12 @@ func startStop(net *Network, quit chan struct{}, nodeCount int) {
return
}
timer.Reset(3 * time.Second)
select {
case <-quit:
log.Info("Terminating simulation loop")
return
case <-time.After(3 * time.Second):
case <-timer.C:
}
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 {
// Wait until all connections from the snapshot are established.
case <-allConnected:
// Make sure that we do not wait forever.
case <-time.After(snapshotLoadTimeout):
case <-snapshotLoadTimeoutTimer.C:
return errors.New("snapshot connections not established")
}
return nil