]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix spurious race using Ticker.Reset
authorRuss Cox <rsc@golang.org>
Fri, 1 Mar 2024 01:14:32 +0000 (20:14 -0500)
committerGopher Robot <gobot@golang.org>
Fri, 8 Mar 2024 22:34:15 +0000 (22:34 +0000)
Ticker.Reset was added in CL 217362 in 2020.
It added the runtime helper modTimer, which is
analogous to startTimer and resetTimer but for tickers.
Unlike those, it does not contain a racerelease, which
means that code synchronizing by starting a ticker
will be diagnosed with a spurious race.

Add racerelease to modTimer and add tests of all
three racereleases (in startTimer, resetTimer, and modTimer).

Also do not call time.resetTimer from elsewhere in runtime,
since that function is only for package time. Use t.reset instead.

For #33184.

Change-Id: Ie40c1ad24911f21e81b1d3cc608cf086ff2bc83d
Reviewed-on: https://go-review.googlesource.com/c/go/+/568340
Auto-Submit: Russ Cox <rsc@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
src/runtime/race/testdata/time_test.go [new file with mode: 0644]
src/runtime/time.go

diff --git a/src/runtime/race/testdata/time_test.go b/src/runtime/race/testdata/time_test.go
new file mode 100644 (file)
index 0000000..820d7c4
--- /dev/null
@@ -0,0 +1,116 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package race_test
+
+import (
+       "testing"
+       "time"
+)
+
+func TestNoRaceAfterFunc(_ *testing.T) {
+       v := 0
+       _ = v
+       c := make(chan int)
+       f := func() {
+               v = 1
+               c <- 0
+       }
+       v = 2
+       time.AfterFunc(1, f)
+       <-c
+       v = 3
+}
+
+func TestNoRaceAfterFuncReset(_ *testing.T) {
+       v := 0
+       _ = v
+       c := make(chan int)
+       f := func() {
+               v = 1
+               c <- 0
+       }
+       t := time.AfterFunc(time.Hour, f)
+       t.Stop()
+       v = 2
+       t.Reset(1)
+       <-c
+       v = 3
+}
+
+func TestNoRaceTimer(_ *testing.T) {
+       v := 0
+       _ = v
+       c := make(chan int)
+       f := func() {
+               v = 1
+               c <- 0
+       }
+       v = 2
+       t := time.NewTimer(1)
+       go func() {
+               <-t.C
+               f()
+       }()
+       <-c
+       v = 3
+}
+
+func TestNoRaceTimerReset(_ *testing.T) {
+       v := 0
+       _ = v
+       c := make(chan int)
+       f := func() {
+               v = 1
+               c <- 0
+       }
+       t := time.NewTimer(time.Hour)
+       go func() {
+               <-t.C
+               f()
+       }()
+       t.Stop()
+       v = 2
+       t.Reset(1)
+       <-c
+       v = 3
+}
+
+func TestNoRaceTicker(_ *testing.T) {
+       v := 0
+       _ = v
+       c := make(chan int)
+       f := func() {
+               v = 1
+               c <- 0
+       }
+       v = 2
+       t := time.NewTicker(1)
+       go func() {
+               <-t.C
+               f()
+       }()
+       <-c
+       v = 3
+}
+
+func TestNoRaceTickerReset(_ *testing.T) {
+       v := 0
+       _ = v
+       c := make(chan int)
+       f := func() {
+               v = 1
+               c <- 0
+       }
+       t := time.NewTicker(time.Hour)
+       go func() {
+               <-t.C
+               f()
+       }()
+       t.Stop()
+       v = 2
+       t.Reset(1)
+       <-c
+       v = 3
+}
index b509d99b80d30ddf6bcb11ffe9653feec0a3b979..cee0197907794ae180c8db85229e28c686fcb2f1 100644 (file)
@@ -295,6 +295,9 @@ func resetTimer(t *timer, when int64) bool {
 //
 //go:linkname modTimer time.modTimer
 func modTimer(t *timer, when, period int64) {
+       if raceenabled {
+               racerelease(unsafe.Pointer(t))
+       }
        t.modify(when, period, t.f, t.arg, t.seq)
 }