From 61fa4dffed09fb8cad42837dbc5fc1275d09624a Mon Sep 17 00:00:00 2001 From: Heschi Kreinick Date: Thu, 5 Dec 2019 13:24:16 -0500 Subject: [PATCH] internal/memoize: fix race on read of handle.function Late into CL 206879 I started nulling out a handle's function when the handle finished running. That invalidated a previous assumption that the field was immutable. Fix the assumption, and since the case of having multiple computations in flight is at least a little bit possible, try harder to avoid duplicate work. Fixes golang/go#35995. Change-Id: Ib5e3640f931f95e35748f28f5a82cf75585b305d Reviewed-on: https://go-review.googlesource.com/c/tools/+/210077 Run-TryBot: Heschi Kreinick Reviewed-by: Rebecca Stambler TryBot-Result: Gobot Gobot --- internal/memoize/memoize.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/internal/memoize/memoize.go b/internal/memoize/memoize.go index 8660111f99..232692c391 100644 --- a/internal/memoize/memoize.go +++ b/internal/memoize/memoize.go @@ -193,8 +193,14 @@ func (h *Handle) run(ctx context.Context) interface{} { h.cancel = cancel h.state = stateRunning h.done = make(chan struct{}) + function := h.function // Read under the lock go func() { - v := h.function(childCtx) + // Just in case the function does something expensive without checking + // the context, double-check we're still alive. + if childCtx.Err() != nil { + return + } + v := function(childCtx) if childCtx.Err() != nil { return }