1
0
mirror of https://github.com/golang/go synced 2024-11-16 22:04:50 -07:00

context: add lock in Cause to avoid race

Change-Id: I8d970e8db859bdd17390cfbc22cc2ba0d326ed0c
Reviewed-on: https://go-review.googlesource.com/c/go/+/453735
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Reviewed-by: Sameer Ajmani <sameer@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
This commit is contained in:
Ian Lance Taylor 2022-11-28 10:33:04 -08:00 committed by Gopher Robot
parent fd22b0bf89
commit 61f5a672ed
3 changed files with 23 additions and 0 deletions

View File

@ -285,6 +285,8 @@ func withCancel(parent Context) *cancelCtx {
// Cause returns nil if c has not been canceled yet. // Cause returns nil if c has not been canceled yet.
func Cause(c Context) error { func Cause(c Context) error {
if cc, ok := c.Value(&cancelCtxKey).(*cancelCtx); ok { if cc, ok := c.Value(&cancelCtxKey).(*cancelCtx); ok {
cc.mu.Lock()
defer cc.mu.Unlock()
return cc.cause return cc.cause
} }
return nil return nil

View File

@ -5,6 +5,7 @@
package context package context
import ( import (
"errors"
"fmt" "fmt"
"math/rand" "math/rand"
"runtime" "runtime"
@ -934,3 +935,22 @@ func XTestCause(t testingT) {
} }
} }
} }
func XTestCauseRace(t testingT) {
cause := errors.New("TestCauseRace")
ctx, cancel := WithCancelCause(Background())
go func() {
cancel(cause)
}()
for {
// Poll Cause, rather than waiting for Done, to test that
// access to the underlying cause is synchronized properly.
if err := Cause(ctx); err != nil {
if err != cause {
t.Errorf("Cause returned %v, want %v", err, cause)
}
break
}
runtime.Gosched()
}
}

View File

@ -30,3 +30,4 @@ func TestInvalidDerivedFail(t *testing.T) { XTestInvalidDerivedFail
func TestDeadlineExceededSupportsTimeout(t *testing.T) { XTestDeadlineExceededSupportsTimeout(t) } func TestDeadlineExceededSupportsTimeout(t *testing.T) { XTestDeadlineExceededSupportsTimeout(t) }
func TestCustomContextGoroutines(t *testing.T) { XTestCustomContextGoroutines(t) } func TestCustomContextGoroutines(t *testing.T) { XTestCustomContextGoroutines(t) }
func TestCause(t *testing.T) { XTestCause(t) } func TestCause(t *testing.T) { XTestCause(t) }
func TestCauseRace(t *testing.T) { XTestCauseRace(t) }