]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: use small struct TestSynctest to ensure cleanups run
authorDamien Neil <dneil@google.com>
Fri, 6 Jun 2025 19:59:04 +0000 (12:59 -0700)
committerDamien Neil <dneil@google.com>
Mon, 9 Jun 2025 18:15:04 +0000 (11:15 -0700)
Finalizers and cleanup funcs weren't running on the windows-arm64
builder. Put finalizers/cleanups on a small struct containing a pointer
rather than an *int, which fixes the problem.

Also uncomment a synctest.Wait that was accidentally commented out.

Fixes #73977

Change-Id: Ia6f18d74d6fccf2c5a9222317977c7458d67f158
Reviewed-on: https://go-review.googlesource.com/c/go/+/679696
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
src/runtime/testdata/testsynctest/main.go

index b47e3fcfc9bd558e21cc3560b0d6ef81564fb858..973d3eac0273fd2de608ada9c2c7fea0e54d5db3 100644 (file)
@@ -9,6 +9,7 @@ import (
        "runtime"
        "runtime/metrics"
        "sync/atomic"
+       "unsafe"
 )
 
 // This program ensures system goroutines (GC workers, finalizer goroutine)
@@ -27,6 +28,11 @@ func numGCCycles() uint64 {
        return samples[0].Value.Uint64()
 }
 
+type T struct {
+       v int
+       p unsafe.Pointer
+}
+
 func main() {
        // Channels created by a finalizer and cleanup func registered within the bubble.
        var (
@@ -36,8 +42,8 @@ func main() {
        synctest.Run(func() {
                // Start the finalizer and cleanup goroutines.
                {
-                       p := new(int)
-                       runtime.SetFinalizer(p, func(*int) {
+                       p := new(T)
+                       runtime.SetFinalizer(p, func(*T) {
                                ch := make(chan struct{})
                                finalizerCh.Store(&ch)
                        })
@@ -47,35 +53,35 @@ func main() {
                        }, struct{}{})
                }
                startingCycles := numGCCycles()
-               ch1 := make(chan *int)
-               ch2 := make(chan *int)
+               ch1 := make(chan *T)
+               ch2 := make(chan *T)
                defer close(ch1)
                go func() {
-                       for i := range ch1 {
-                               v := *i + 1
-                               ch2 <- &v
+                       for range ch1 {
+                               ch2 <- &T{}
                        }
                }()
-               for {
+               const iterations = 1000
+               for range iterations {
                        // Make a lot of short-lived allocations to get the GC working.
-                       for i := 0; i < 1000; i++ {
-                               v := new(int)
-                               *v = i
+                       for range 1000 {
+                               v := new(T)
                                // Set finalizers on these values, just for added stress.
-                               runtime.SetFinalizer(v, func(*int) {})
+                               runtime.SetFinalizer(v, func(*T) {})
                                ch1 <- v
                                <-ch2
                        }
 
                        // If we've improperly put a GC goroutine into the synctest group,
                        // this Wait is going to hang.
-                       //synctest.Wait()
+                       synctest.Wait()
 
                        // End the test after a couple of GC cycles have passed.
                        if numGCCycles()-startingCycles > 1 && finalizerCh.Load() != nil && cleanupCh.Load() != nil {
-                               break
+                               return
                        }
                }
+               println("finalizers/cleanups failed to run after", iterations, "cycles")
        })
        // Close the channels created by the finalizer and cleanup func.
        // If the funcs improperly ran inside the bubble, these channels are bubbled