accounting: fix goroutine leak in ResetCounters

ResetCounters unconditionally restarted the average loop, spawning a
ticker goroutine that pinned the StatsInfo even when no loop had been
running before. statsGroups.delete calls ResetCounters on every removed
group, so deleting N stats groups leaked N goroutines and prevented GC
of the underlying StatsInfo objects.

Only restart the loop if it was active before the reset.

(cherry picked from commit a8f102ce8f)
This commit is contained in:
Nick Craig-Wood
2026-05-12 15:44:55 +01:00
parent 660b630979
commit 3f80fe0b07

View File

@@ -730,9 +730,15 @@ func (s *StatsInfo) ResetCounters() {
s.startedTransfers = nil
s.oldDuration = 0
// Only restart the average loop if it was running. Otherwise
// ResetCounters would spawn a goroutine that pins the StatsInfo,
// leaking memory when called on stats that never started the loop.
wasStarted := s.average.started
s._stopAverageLoop()
s.average = averageValues{}
s._startAverageLoop()
if wasStarted {
s._startAverageLoop()
}
}
// ResetErrors sets the errors count to 0 and resets lastError, fatalError and retryError