mirror of
https://github.com/golang/go.git
synced 2026-02-06 09:50:02 +00:00
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>
This commit is contained in:
parent
c6f882f6c5
commit
1a53ce9734
1 changed files with 9 additions and 9 deletions
|
|
@ -286,6 +286,10 @@ func withCancel(parent Context) *cancelCtx {
|
|||
// Otherwise Cause(c) returns the same value as c.Err().
|
||||
// Cause returns nil if c has not been canceled yet.
|
||||
func Cause(c Context) error {
|
||||
err := c.Err()
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if cc, ok := c.Value(&cancelCtxKey).(*cancelCtx); ok {
|
||||
cc.mu.Lock()
|
||||
cause := cc.cause
|
||||
|
|
@ -293,16 +297,12 @@ func Cause(c Context) error {
|
|||
if cause != nil {
|
||||
return cause
|
||||
}
|
||||
// Either this context is not canceled,
|
||||
// or it is canceled and the cancellation happened in a
|
||||
// custom context implementation rather than a *cancelCtx.
|
||||
// The parent cancelCtx doesn't have a cause,
|
||||
// so c must have been canceled in some custom context implementation.
|
||||
}
|
||||
// There is no cancelCtxKey value with a cause, so we know that c is
|
||||
// not a descendant of some canceled Context created by WithCancelCause.
|
||||
// Therefore, there is no specific cause to return.
|
||||
// If this is not one of the standard Context types,
|
||||
// it might still have an error even though it won't have a cause.
|
||||
return c.Err()
|
||||
// We don't have a cause to return from a parent cancelCtx,
|
||||
// so return the context's error.
|
||||
return err
|
||||
}
|
||||
|
||||
// AfterFunc arranges to call f in its own goroutine after ctx is canceled.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue