aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJelle van den Hooff <jelle@vandenhooff.name>2023-06-21 18:28:05 -0700
committerCarlos Amedee <carlos@golang.org>2023-06-29 15:53:20 +0000
commit4db13d762ba3f3487677087a3c5a6221b4c3bd8f (patch)
treedca6b8d8c361e16c25a6d888f369fa3987e335a5
parent08a58dd8b6337c9bac93face4c386a918a3dd97b (diff)
downloadgo-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.go1
-rw-r--r--src/runtime/race/testdata/mop_test.go37
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()
+}