diff options
author | Jelle van den Hooff <jelle@vandenhooff.name> | 2023-06-21 18:28:05 -0700 |
---|---|---|
committer | Carlos Amedee <carlos@golang.org> | 2023-06-29 15:53:20 +0000 |
commit | 4db13d762ba3f3487677087a3c5a6221b4c3bd8f (patch) | |
tree | dca6b8d8c361e16c25a6d888f369fa3987e335a5 | |
parent | 08a58dd8b6337c9bac93face4c386a918a3dd97b (diff) | |
download | go-4db13d762ba3f3487677087a3c5a6221b4c3bd8f.tar.gz go-4db13d762ba3f3487677087a3c5a6221b4c3bd8f.zip |
[release-branch.go1.20] runtime: set raceignore to zero when starting a new goroutine
When reusing a g struct the runtime did not reset
g.raceignore. Initialize raceignore to zero when initially
setting racectx.
A goroutine can end with a non-zero raceignore if it exits
after calling runtime.RaceDisable without a matching
runtime.RaceEnable. If that goroutine's g is later reused
the race detector is in a weird state: the underlying
g.racectx is active, yet g.raceignore is non-zero, and
raceacquire/racerelease which check g.raceignore become
no-ops. This causes the race detector to report races when
there are none.
For #60934
Fixes #60949
Change-Id: Ib8e412f11badbaf69a480f03740da70891f4093f
Reviewed-on: https://go-review.googlesource.com/c/go/+/505055
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
(cherry picked from commit 48dbb6227acf3ebc8ac21924567aa2b6d5064915)
Reviewed-on: https://go-review.googlesource.com/c/go/+/505676
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
-rw-r--r-- | src/runtime/proc.go | 1 | ||||
-rw-r--r-- | src/runtime/race/testdata/mop_test.go | 37 |
2 files changed, 38 insertions, 0 deletions
diff --git a/src/runtime/proc.go b/src/runtime/proc.go index bf2a33ea92..96908fc6a5 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -4351,6 +4351,7 @@ func newproc1(fn *funcval, callergp *g, callerpc uintptr) *g { pp.goidcache++ if raceenabled { newg.racectx = racegostart(callerpc) + newg.raceignore = 0 if newg.labels != nil { // See note in proflabel.go on labelSync's role in synchronizing // with the reads in the signal handler. diff --git a/src/runtime/race/testdata/mop_test.go b/src/runtime/race/testdata/mop_test.go index 0d79091df4..4a9ce2631e 100644 --- a/src/runtime/race/testdata/mop_test.go +++ b/src/runtime/race/testdata/mop_test.go @@ -2092,3 +2092,40 @@ func TestNoRaceTinyAlloc(t *testing.T) { <-done } } + +func TestNoRaceIssue60934(t *testing.T) { + // Test that runtime.RaceDisable state doesn't accidentally get applied to + // new goroutines. + + // Create several goroutines that end after calling runtime.RaceDisable. + var wg sync.WaitGroup + ready := make(chan struct{}) + wg.Add(32) + for i := 0; i < 32; i++ { + go func() { + <-ready // ensure we have multiple goroutines running at the same time + runtime.RaceDisable() + wg.Done() + }() + } + close(ready) + wg.Wait() + + // Make sure race detector still works. If the runtime.RaceDisable state + // leaks, the happens-before edges here will be ignored and a race on x will + // be reported. + var x int + ch := make(chan struct{}, 0) + wg.Add(2) + go func() { + x = 1 + ch <- struct{}{} + wg.Done() + }() + go func() { + <-ch + _ = x + wg.Done() + }() + wg.Wait() +} |