mirror of https://github.com/golang/go.git
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. Fixes #60934 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>
This commit is contained in:
parent
3adcce5ae7
commit
48dbb6227a
|
|
@ -4570,6 +4570,7 @@ func newproc1(fn *funcval, callergp *g, callerpc uintptr) *g {
|
||||||
pp.goidcache++
|
pp.goidcache++
|
||||||
if raceenabled {
|
if raceenabled {
|
||||||
newg.racectx = racegostart(callerpc)
|
newg.racectx = racegostart(callerpc)
|
||||||
|
newg.raceignore = 0
|
||||||
if newg.labels != nil {
|
if newg.labels != nil {
|
||||||
// See note in proflabel.go on labelSync's role in synchronizing
|
// See note in proflabel.go on labelSync's role in synchronizing
|
||||||
// with the reads in the signal handler.
|
// with the reads in the signal handler.
|
||||||
|
|
|
||||||
|
|
@ -2093,3 +2093,40 @@ func TestNoRaceTinyAlloc(t *testing.T) {
|
||||||
<-done
|
<-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()
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue