aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/testdata
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/testdata')
-rw-r--r--src/runtime/testdata/testsynctest/main.go67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/runtime/testdata/testsynctest/main.go b/src/runtime/testdata/testsynctest/main.go
new file mode 100644
index 0000000000..d2cbc99258
--- /dev/null
+++ b/src/runtime/testdata/testsynctest/main.go
@@ -0,0 +1,67 @@
+// Copyright 2024 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 main
+
+import (
+ "internal/synctest"
+ "runtime"
+ "runtime/metrics"
+)
+
+// This program ensures system goroutines (GC workers, finalizer goroutine)
+// started from within a synctest bubble do not participate in that bubble.
+//
+// To ensure none of these goroutines start before synctest.Run,
+// it must have no dependencies on packages which may start system goroutines.
+// This includes the os package, which creates finalizers at init time.
+
+func numGCCycles() uint64 {
+ samples := []metrics.Sample{{Name: "/gc/cycles/total:gc-cycles"}}
+ metrics.Read(samples)
+ if samples[0].Value.Kind() == metrics.KindBad {
+ panic("metric not supported")
+ }
+ return samples[0].Value.Uint64()
+}
+
+func main() {
+ synctest.Run(func() {
+ // Start the finalizer goroutine.
+ p := new(int)
+ runtime.SetFinalizer(p, func(*int) {})
+
+ startingCycles := numGCCycles()
+ ch1 := make(chan *int)
+ ch2 := make(chan *int)
+ defer close(ch1)
+ go func() {
+ for i := range ch1 {
+ v := *i + 1
+ ch2 <- &v
+ }
+ }()
+ for {
+ // Make a lot of short-lived allocations to get the GC working.
+ for i := 0; i < 1000; i++ {
+ v := new(int)
+ *v = i
+ // Set finalizers on these values, just for added stress.
+ runtime.SetFinalizer(v, func(*int) {})
+ ch1 <- v
+ <-ch2
+ }
+
+ // If we've improperly put a GC goroutine into the synctest group,
+ // this Wait is going to hang.
+ synctest.Wait()
+
+ // End the test after a couple of GC cycles have passed.
+ if numGCCycles()-startingCycles > 1 {
+ break
+ }
+ }
+ })
+ println("success")
+}