diff --git a/CHANGELOG.md b/CHANGELOG.md index 07ca71af073..4184788c8ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ ## Unreleased - Add OpenStack Metrics Scaler ([#1382](https://github.com/kedacore/keda/issues/1382)) +- Fixed goroutine leaks in usage of timers ([#1704](https://github.com/kedacore/keda/pull/1704)) ### New diff --git a/pkg/scalers/external_scaler.go b/pkg/scalers/external_scaler.go index 9063aec9335..eb7c73a69d0 100644 --- a/pkg/scalers/external_scaler.go +++ b/pkg/scalers/external_scaler.go @@ -231,23 +231,28 @@ func (s *externalPushScaler) Run(ctx context.Context, active chan<- bool) { // retry on error from runWithLog() starting by 2 sec backing off * 2 with a max of 1 minute retryDuration := time.Second * 2 - retryBackoff := func() <-chan time.Time { - ch := time.After(retryDuration) + // the caller of this function needs to ensure that they call Stop() on the resulting + // timer, to release background resources. + retryBackoff := func() *time.Timer { + tmr := time.NewTimer(retryDuration) retryDuration *= time.Second * 2 if retryDuration > time.Minute*1 { retryDuration = time.Minute * 1 } - return ch + return tmr } // start the first run without delay runWithLog() for { + backoffTimer := retryBackoff() select { case <-ctx.Done(): + backoffTimer.Stop() return - case <-retryBackoff(): + case <-backoffTimer.C: + backoffTimer.Stop() runWithLog() } } diff --git a/pkg/scaling/scale_handler.go b/pkg/scaling/scale_handler.go index 9d11761f2b0..df542a44c89 100644 --- a/pkg/scaling/scale_handler.go +++ b/pkg/scaling/scale_handler.go @@ -140,12 +140,15 @@ func (h *scaleHandler) startScaleLoop(ctx context.Context, withTriggers *kedav1a pollingInterval := getPollingInterval(withTriggers) logger.V(1).Info("Watching with pollingInterval", "PollingInterval", pollingInterval) + tmr := time.NewTimer(pollingInterval) for { select { - case <-time.After(pollingInterval): + case <-tmr.C: h.checkScalers(ctx, scalableObject, scalingMutex) + tmr.Stop() case <-ctx.Done(): logger.V(1).Info("Context canceled") + tmr.Stop() return } }