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>
// Cause returns nil if c has not been canceled yet.
func Cause(c Context) error {
if cc, ok := c.Value(&cancelCtxKey).(*cancelCtx); ok {
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
return cc.cause
}
return nil
package context
import (
+ "errors"
"fmt"
"math/rand"
"runtime"
}
}
}
+
+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()
+ }
+}
func TestDeadlineExceededSupportsTimeout(t *testing.T) { XTestDeadlineExceededSupportsTimeout(t) }
func TestCustomContextGoroutines(t *testing.T) { XTestCustomContextGoroutines(t) }
func TestCause(t *testing.T) { XTestCause(t) }
+func TestCauseRace(t *testing.T) { XTestCauseRace(t) }