aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/race/testdata
diff options
context:
space:
mode:
authorMichael Anthony Knyszek <mknyszek@google.com>2025-02-25 22:50:10 +0000
committerGopher Robot <gobot@golang.org>2025-05-14 19:12:19 -0700
commit3ea94ae446727ab75f6baa38444cf49041cb3b16 (patch)
tree78f4f5f812c01ddf21cc946b3f8a507369e28d1e /src/runtime/race/testdata
parentb30fa1bcc411f3a65a6e8f40ff3acdb1526ce0d0 (diff)
downloadgo-3ea94ae446727ab75f6baa38444cf49041cb3b16.tar.xz
runtime: help the race detector detect possible concurrent cleanups
This change makes it so that cleanup goroutines, in race mode, create a fake race context and switch to it, emulating cleanups running on new goroutines. This helps in catching races between cleanups that might run concurrently. Change-Id: I4c4e33054313798d4ac4e5d91ff2487ea3eb4b16 Reviewed-on: https://go-review.googlesource.com/c/go/+/652635 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Michael Knyszek <mknyszek@google.com> Reviewed-by: David Chase <drchase@google.com> Reviewed-by: Michael Pratt <mpratt@google.com>
Diffstat (limited to 'src/runtime/race/testdata')
-rw-r--r--src/runtime/race/testdata/finalizer_test.go41
1 files changed, 41 insertions, 0 deletions
diff --git a/src/runtime/race/testdata/finalizer_test.go b/src/runtime/race/testdata/finalizer_test.go
index 3ac33d2b59..ad6fe717c6 100644
--- a/src/runtime/race/testdata/finalizer_test.go
+++ b/src/runtime/race/testdata/finalizer_test.go
@@ -9,6 +9,7 @@ import (
"sync"
"testing"
"time"
+ "unsafe"
)
func TestNoRaceFin(t *testing.T) {
@@ -66,3 +67,43 @@ func TestRaceFin(t *testing.T) {
time.Sleep(100 * time.Millisecond)
y = 66
}
+
+func TestNoRaceCleanup(t *testing.T) {
+ c := make(chan bool)
+ go func() {
+ x := new(string)
+ y := new(string)
+ runtime.AddCleanup(x, func(y *string) {
+ *y = "foo"
+ }, y)
+ *y = "bar"
+ runtime.KeepAlive(x)
+ c <- true
+ }()
+ <-c
+ runtime.GC()
+ time.Sleep(100 * time.Millisecond)
+}
+
+func TestRaceBetweenCleanups(t *testing.T) {
+ // Allocate struct with pointer to avoid hitting tinyalloc.
+ // Otherwise we can't be sure when the allocation will
+ // be freed.
+ type T struct {
+ v int
+ p unsafe.Pointer
+ }
+ sharedVar := new(int)
+ v0 := new(T)
+ v1 := new(T)
+ cleanup := func(x int) {
+ *sharedVar = x
+ }
+ runtime.AddCleanup(v0, cleanup, 0)
+ runtime.AddCleanup(v1, cleanup, 0)
+ v0 = nil
+ v1 = nil
+
+ runtime.GC()
+ time.Sleep(100 * time.Millisecond)
+}