From 2e46c2ac1d860230a80de5fd7bc85c8c9429d3f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B5=D0=BD=D0=B8=D1=81=20=D0=A2=D0=B5=D0=BB=D1=8E?= =?UTF-8?q?=D1=85?= Date: Wed, 5 Jan 2022 02:14:18 +0700 Subject: [PATCH] admin, reverseproxy: Stop timers if canceled to avoid goroutine leak (#4482) --- caddy.go | 7 ++++++- modules/caddyhttp/reverseproxy/reverseproxy.go | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/caddy.go b/caddy.go index bee4274c7d3..f990d362cfa 100644 --- a/caddy.go +++ b/caddy.go @@ -494,9 +494,10 @@ func finishSettingUp(ctx Context, cfg *Config) error { if cfg.Admin.Config.LoadInterval > 0 { go func() { for { + timer := time.NewTimer(time.Duration(cfg.Admin.Config.LoadInterval)) select { // if LoadInterval is positive, will wait for the interval and then run with new config - case <-time.After(time.Duration(cfg.Admin.Config.LoadInterval)): + case <-timer.C: loadedConfig, err := val.(ConfigLoader).LoadConfig(ctx) if err != nil { Log().Error("loading dynamic config failed", zap.Error(err)) @@ -504,6 +505,10 @@ func finishSettingUp(ctx Context, cfg *Config) error { } runLoadedConfig(loadedConfig) case <-ctx.Done(): + if !timer.Stop() { + // if the timer has been stopped then read from the channel + <-timer.C + } Log().Info("stopping config load interval") return } diff --git a/modules/caddyhttp/reverseproxy/reverseproxy.go b/modules/caddyhttp/reverseproxy/reverseproxy.go index b4189535fd9..eaa7cbf928e 100644 --- a/modules/caddyhttp/reverseproxy/reverseproxy.go +++ b/modules/caddyhttp/reverseproxy/reverseproxy.go @@ -792,10 +792,15 @@ func (lb LoadBalancing) tryAgain(ctx caddy.Context, start time.Time, proxyErr er } // otherwise, wait and try the next available host + timer := time.NewTimer(time.Duration(lb.TryInterval)) select { - case <-time.After(time.Duration(lb.TryInterval)): + case <-timer.C: return true case <-ctx.Done(): + if !timer.Stop() { + // if the timer has been stopped then read from the channel + <-timer.C + } return false } }