From 91cbca941af9c72f45d29220d5ae82dd9ee770dc Mon Sep 17 00:00:00 2001 From: Miccah Date: Tue, 25 Jul 2023 17:09:36 -0500 Subject: [PATCH] Fix data race in context wrapper library (#1546) --- pkg/context/context.go | 9 +++++++-- pkg/context/context_test.go | 6 ++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/pkg/context/context.go b/pkg/context/context.go index 330290808..61a9a2e62 100644 --- a/pkg/context/context.go +++ b/pkg/context/context.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "runtime/debug" + "sync" "time" "github.com/go-logr/logr" @@ -28,8 +29,9 @@ type CancelFunc = context.CancelFunc type logCtx struct { // Embed context.Context to get all methods for free. context.Context - log logr.Logger - err *error + log logr.Logger + err *error + errLock *sync.Mutex } // Logger returns a structured logger. @@ -145,8 +147,11 @@ func captureCancelCallstack(ctx logCtx, f context.CancelFunc) (Context, context. if ctx.err == nil { var err error ctx.err = &err + ctx.errLock = &sync.Mutex{} } return ctx, func() { + ctx.errLock.Lock() + defer ctx.errLock.Unlock() // We must check Err() before calling f() since f() sets the error. // If there's already an error, do nothing special. if ctx.Err() != nil { diff --git a/pkg/context/context_test.go b/pkg/context/context_test.go index b896b98bc..6ef93227a 100644 --- a/pkg/context/context_test.go +++ b/pkg/context/context_test.go @@ -212,3 +212,9 @@ func TestErrCallstackTimeoutCancel(t *testing.T) { cancel() assert.Equal(t, err, ctx.Err()) } + +func TestRace(t *testing.T) { + _, cancel := WithCancel(Background()) + go cancel() + cancel() +}