Skip to content

Commit 1a53ce9

Browse files
committed
context: don't return the wrong error when Cause races cancellation
Check to see if a context is canceled at all before checking for the cancellaion cause. If we can't find a cause, use the original error. Avoids a data race where we look for a cause, find none (because the context is not canceled), the context is canceled, and we then return ctx.Err() (even though there is now a cause). Fixes #73390 Change-Id: I97f44aef25c6b02871d987970abfb4c215c5c80e Reviewed-on: https://go-review.googlesource.com/c/go/+/679835 Reviewed-by: Sean Liao <sean@liao.dev> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Cherry Mui <cherryyz@google.com>
1 parent c6f882f commit 1a53ce9

File tree

1 file changed

+10
-10
lines changed

1 file changed

+10
-10
lines changed

src/context/context.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -286,23 +286,23 @@ func withCancel(parent Context) *cancelCtx {
286286
// Otherwise Cause(c) returns the same value as c.Err().
287287
// Cause returns nil if c has not been canceled yet.
288288
func Cause(c Context) error {
289+
err := c.Err()
290+
if err == nil {
291+
return nil
292+
}
289293
if cc, ok := c.Value(&cancelCtxKey).(*cancelCtx); ok {
290294
cc.mu.Lock()
291295
cause := cc.cause
292296
cc.mu.Unlock()
293297
if cause != nil {
294298
return cause
295299
}
296-
// Either this context is not canceled,
297-
// or it is canceled and the cancellation happened in a
298-
// custom context implementation rather than a *cancelCtx.
299-
}
300-
// There is no cancelCtxKey value with a cause, so we know that c is
301-
// not a descendant of some canceled Context created by WithCancelCause.
302-
// Therefore, there is no specific cause to return.
303-
// If this is not one of the standard Context types,
304-
// it might still have an error even though it won't have a cause.
305-
return c.Err()
300+
// The parent cancelCtx doesn't have a cause,
301+
// so c must have been canceled in some custom context implementation.
302+
}
303+
// We don't have a cause to return from a parent cancelCtx,
304+
// so return the context's error.
305+
return err
306306
}
307307

308308
// AfterFunc arranges to call f in its own goroutine after ctx is canceled.

0 commit comments

Comments
 (0)