From ad3d2cc8efc12e2aa7a0144ed4a11169193646e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jerome=20K=C3=BCttner?= Date: Mon, 6 Dec 2021 17:43:38 +0100 Subject: [PATCH 1/2] Fix memory leak in upgrade action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fixes helm/helm#10439 Signed-off-by: Jerome Küttner --- pkg/action/upgrade.go | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/pkg/action/upgrade.go b/pkg/action/upgrade.go index a4a1a0883..97f7334c3 100644 --- a/pkg/action/upgrade.go +++ b/pkg/action/upgrade.go @@ -321,9 +321,17 @@ func (u *Upgrade) performUpgrade(ctx context.Context, originalRelease, upgradedR return nil, err } rChan := make(chan resultMessage) + ctxChan := make(chan resultMessage) + doneChan := make(chan interface{}) go u.releasingUpgrade(rChan, upgradedRelease, current, target, originalRelease) - go u.handleContext(ctx, rChan, upgradedRelease) - result := <-rChan + go u.handleContext(ctx, doneChan, ctxChan, upgradedRelease) + var result resultMessage + select { + case result = <-rChan: + doneChan <- true + case result = <-ctxChan: + close(rChan) + } return result.r, result.e } @@ -341,13 +349,17 @@ func (u *Upgrade) reportToPerformUpgrade(c chan<- resultMessage, rel *release.Re } // Setup listener for SIGINT and SIGTERM -func (u *Upgrade) handleContext(ctx context.Context, c chan<- resultMessage, upgradedRelease *release.Release) { - +func (u *Upgrade) handleContext(ctx context.Context, done chan interface{}, c chan<- resultMessage, upgradedRelease *release.Release) { go func() { - <-ctx.Done() - err := ctx.Err() - // when the atomic flag is set the ongoing release finish first and doesn't give time for the rollback happens. - u.reportToPerformUpgrade(c, upgradedRelease, kube.ResourceList{}, err) + select { + case <-ctx.Done(): + err := ctx.Err() + + // when the atomic flag is set the ongoing release finish first and doesn't give time for the rollback happens. + u.reportToPerformUpgrade(c, upgradedRelease, kube.ResourceList{}, err) + case <-done: + return + } }() } func (u *Upgrade) releasingUpgrade(c chan<- resultMessage, upgradedRelease *release.Release, current kube.ResourceList, target kube.ResourceList, originalRelease *release.Release) { From 9a492f8240d177d97d59c87d168059fa6181f96e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jerome=20K=C3=BCttner?= Date: Mon, 6 Dec 2021 18:07:47 +0100 Subject: [PATCH 2/2] Channel should remain open if there is still a routine that wants to write into it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jerome Küttner --- pkg/action/upgrade.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pkg/action/upgrade.go b/pkg/action/upgrade.go index 97f7334c3..1e7054118 100644 --- a/pkg/action/upgrade.go +++ b/pkg/action/upgrade.go @@ -325,15 +325,13 @@ func (u *Upgrade) performUpgrade(ctx context.Context, originalRelease, upgradedR doneChan := make(chan interface{}) go u.releasingUpgrade(rChan, upgradedRelease, current, target, originalRelease) go u.handleContext(ctx, doneChan, ctxChan, upgradedRelease) - var result resultMessage select { - case result = <-rChan: + case result := <-rChan: doneChan <- true - case result = <-ctxChan: - close(rChan) + return result.r, result.e + case result := <-ctxChan: + return result.r, result.e } - - return result.r, result.e } // Function used to lock the Mutex, this is important for the case when the atomic flag is set.