From ab0b46164e56549ddf84e80838f5166c26db2b18 Mon Sep 17 00:00:00 2001 From: Will Hughes Date: Thu, 1 Aug 2019 19:42:18 -0700 Subject: [PATCH] go reactive: Cancel context after each reactive Run Summary: Some pieces of code will hold onto the context waiting for it to be done (usually in a goroutine). This means that all the objects that are stored on the context are held until the original context is marked as "done". This would not happen until the websocket/http request finishes. So for continous requests we have a leak where each intermediary context is holding onto the entire cache stack (and anything else on the context) until we reset the websocket connection. This commit adds a cancel to context for each reactive.Run. This should allow all code that depends on the context.Done() to be able to clear between runs. --- reactive/rerunner.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/reactive/rerunner.go b/reactive/rerunner.go index 160e3291c..abed5e7fb 100644 --- a/reactive/rerunner.go +++ b/reactive/rerunner.go @@ -369,7 +369,13 @@ func (r *Rerunner) run() { time.Sleep(WriteThenReadDelay) } r.cache.cleanInvalidated() - ctx := context.WithValue(r.ctx, cacheKey{}, r.cache) + + // Cancel the context passed to "run". Canceling the context ensures that + // libraries let go of the context when they might otherwise hold onto it long + // past this run. + ctx, cancel := context.WithCancel(r.ctx) + defer cancel() + ctx = context.WithValue(ctx, cacheKey{}, r.cache) ctx = context.WithValue(ctx, dependencySetKey{}, &dependencySet{}) currentComputation, err := run(ctx, r.f)