Skip to content

Commit 3313bbb

Browse files
committed
runtime: add race annotations in IncNonDefault
Also use CompareAndSwap to make the code actually less racy. Added a test which will be meaningful when run under the race detector (tested it -race with broken fix in runtime, it failed). Fixes #64649 Change-Id: I5972e08901d1adc8ba74858edad7eba91be1b0ce Reviewed-on: https://go-review.googlesource.com/c/go/+/549796 Run-TryBot: David Chase <[email protected]> Reviewed-by: Mauri de Souza Meneguzzo <[email protected]> Reviewed-by: Cherry Mui <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent b60bf8f commit 3313bbb

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

src/internal/godebug/godebug_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package godebug_test
77
import (
88
"fmt"
99
. "internal/godebug"
10+
"internal/race"
1011
"internal/testenv"
1112
"os"
1213
"os/exec"
@@ -70,6 +71,36 @@ func TestMetrics(t *testing.T) {
7071
}
7172
}
7273

74+
// TestPanicNilRace checks for a race in the runtime caused by use of runtime
75+
// atomics (not visible to usual race detection) to install the counter for
76+
// non-default panic(nil) semantics. For #64649.
77+
func TestPanicNilRace(t *testing.T) {
78+
if !race.Enabled {
79+
t.Skip("Skipping test intended for use with -race.")
80+
}
81+
if os.Getenv("GODEBUG") != "panicnil=1" {
82+
cmd := testenv.CleanCmdEnv(testenv.Command(t, os.Args[0], "-test.run=^TestPanicNilRace$", "-test.v", "-test.parallel=2", "-test.count=1"))
83+
cmd.Env = append(cmd.Env, "GODEBUG=panicnil=1")
84+
out, err := cmd.CombinedOutput()
85+
t.Logf("output:\n%s", out)
86+
87+
if err != nil {
88+
t.Errorf("Was not expecting a crash")
89+
}
90+
return
91+
}
92+
93+
test := func(t *testing.T) {
94+
t.Parallel()
95+
defer func() {
96+
recover()
97+
}()
98+
panic(nil)
99+
}
100+
t.Run("One", test)
101+
t.Run("Two", test)
102+
}
103+
73104
func TestCmdBisect(t *testing.T) {
74105
testenv.MustHaveGoBuild(t)
75106
out, err := exec.Command("go", "run", "cmd/vendor/golang.org/x/tools/cmd/bisect", "GODEBUG=buggy=1#PATTERN", os.Args[0], "-test.run=^TestBisectTestCase$").CombinedOutput()

src/runtime/runtime.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,15 @@ func (g *godebugInc) IncNonDefault() {
172172
// *godebug.Setting.
173173
inc = new(func())
174174
*inc = (*newInc)(g.name)
175-
g.inc.Store(inc)
175+
if raceenabled {
176+
racerelease(unsafe.Pointer(&g.inc))
177+
}
178+
if !g.inc.CompareAndSwap(nil, inc) {
179+
inc = g.inc.Load()
180+
}
181+
}
182+
if raceenabled {
183+
raceacquire(unsafe.Pointer(&g.inc))
176184
}
177185
(*inc)()
178186
}

0 commit comments

Comments
 (0)