Conversation
Signed-off-by: Effi-S <effi.szt@gmail.com>
Effi-S
marked this pull request as ready for review
August 18, 2026 21:10
AkramBitar
reviewed
Aug 18, 2026
Contributor
There was a problem hiding this comment.
Two items:
1. Ticker drops the pause between scans (blocking). A Ticker fires on a fixed grid with a 1-slot buffer. Once a scan exceeds sleepTimeout (one GetStatus per locked token, sleepTimeout is 2s in prod), the select finds a stale tick already waiting and rescans with zero pause — hammering the status provider. time.After always gave a full gap after the scan. Use a reusable Timer instead: same one allocation, original semantics.
timer := time.NewTimer(d.sleepTimeout)
defer timer.Stop()
// in the inner loop, before the select:
timer.Reset(d.sleepTimeout)
select {
case <-timer.C:
case <-ctx.Done():
return
}2. Panic on non-positive interval (minor). NewTicker/NewTimer panic when sleepTimeout <= 0; time.After did not. Clamp it in NewLocker.
AkramBitar
requested changes
Aug 18, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #2127
Document severity: MEDIUM · Verified priority: Low · Effort: Low · Type: Task
Old issue reference
[RUN]selector/simple/inmemory/locker.gotime.Afterin scan sleep loop; should beTickerIntent
The scan goroutine in the in-memory locker uses
time.After(d.sleepTimeout)inside a
for { select { } }loop. A new timer is allocated on everyiteration. Although the
ctx.Done()branch provides an exit path, eachiteration before exit leaks the timer for up to
sleepTimeoutduration.Expected Outcomes
time.Tickerdrives the scan sleep instead of per-iteration timers.ticker.Stop()is called viadeferwhen the goroutine exits.Todo List
ticker := time.NewTicker(d.sleepTimeout)before the outer loop.defer ticker.Stop()immediately after.case <-time.After(d.sleepTimeout):withcase <-ticker.C:.Relevant Context
token/services/selector/simple/inmemory/locker.goStatus in current code
Not a leak on Go 1.26, but the
Tickersuggestion has independent merit. Line numbers have shifted: the loop is now attoken/services/selector/simple/inmemory/locker.go:430, not 264–284.The call is now at
token/services/selector/simple/inmemory/locker.go:430(
case <-time.After(d.sleepTimeout):), inside the scan goroutine's sleep loop.On the leak claim:
go.moddeclaresgo 1.26.5. Per the Go 1.23 release notes: "Timers and Tickers that are no longer referred to by the program become eligible for garbage collection immediately, even if theirStopmethods have not been called. Earlier versions of Go did not collect unstopped Timers until after they had fired and never collected unstopped Tickers." The timer returned bytime.Afterbecomes unreachable the moment theselectcompletes, so it is collectable immediately rather than surviving until it fires. The document's premise — that the timer is retained for its full duration — describes pre-1.23 runtime behaviour and does not hold on this toolchain.So "each iteration before exit leaks the timer for up to
sleepTimeoutduration" is not truehere — the timer is collectable as soon as its iteration's
selectreturns.This is the one item in the timer group where the suggested change is still worth making on
its own merits. A single
time.NewTickercreated before the loop withdefer ticker.Stop()is genuinely clearer than re-arming a timer every pass through a hot scan loop, and it
expresses the fixed-interval intent directly. It also avoids one allocation per scan cycle,
which is not a leak but is not free either.
Recommendation: fold into unrelated work in this file rather than tracking as a standalone
change. Kept open at Low for that purpose.
Severity and priority
The source document rated this MEDIUM. Re-checked against this repository at
origin/mainwithgo 1.26.5on 2026-08-04, the priority is Low for thereasons in Status in current code above.
Effort
Low