You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Server.Close runs registered close hooks under an optional CloseCallbackBudget: once a positive budget is exhausted, runPhase skips the remaining hooks in that phase. Internal, lifecycle-critical hooks are registered through the same mechanism as user callbacks, so a tight budget can skip them:
LimitFilter.StopCleanup (PreShutdown, filters.go) — same exposure, pre-existing.
With the default budget of 0 nothing is skipped, so this is latent, not a live bug. But mixing internal teardown with budgeted user callbacks means an operator who sets a budget to bound user callbacks can silently break internal shutdown.
Suggested direction
Exempt internally-registered lifecycle hooks from CloseCallbackBudget — e.g. a separate non-budgeted registration path (or a flag on the hook) so the budget only ever caps user-supplied callbacks. Internal teardown should always run.
Surfaced during the self-review of #150; out of scope there.
Problem
Server.Closeruns registered close hooks under an optionalCloseCallbackBudget: once a positive budget is exhausted,runPhaseskips the remaining hooks in that phase. Internal, lifecycle-critical hooks are registered through the same mechanism as user callbacks, so a tight budget can skip them:stopResync(PreShutdown), added in fix(stream): make the broadcast the only writer of the pool cache #150 — a skipped stop leaves the worker goroutine alive intoStorage.Close, i.e. a goroutine leak and a possible read-after-close on embedded storages.LimitFilter.StopCleanup(PreShutdown,filters.go) — same exposure, pre-existing.With the default budget of 0 nothing is skipped, so this is latent, not a live bug. But mixing internal teardown with budgeted user callbacks means an operator who sets a budget to bound user callbacks can silently break internal shutdown.
Suggested direction
Exempt internally-registered lifecycle hooks from
CloseCallbackBudget— e.g. a separate non-budgeted registration path (or a flag on the hook) so the budget only ever caps user-supplied callbacks. Internal teardown should always run.Surfaced during the self-review of #150; out of scope there.
🤖 Generated with Claude Code