Source file src/runtime/testdata/testsynctest/main.go

     1  // Copyright 2024 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"internal/synctest"
     9  	"runtime"
    10  	"runtime/metrics"
    11  )
    12  
    13  // This program ensures system goroutines (GC workers, finalizer goroutine)
    14  // started from within a synctest bubble do not participate in that bubble.
    15  //
    16  // To ensure none of these goroutines start before synctest.Run,
    17  // it must have no dependencies on packages which may start system goroutines.
    18  // This includes the os package, which creates finalizers at init time.
    19  
    20  func numGCCycles() uint64 {
    21  	samples := []metrics.Sample{{Name: "/gc/cycles/total:gc-cycles"}}
    22  	metrics.Read(samples)
    23  	if samples[0].Value.Kind() == metrics.KindBad {
    24  		panic("metric not supported")
    25  	}
    26  	return samples[0].Value.Uint64()
    27  }
    28  
    29  func main() {
    30  	synctest.Run(func() {
    31  		// Start the finalizer goroutine.
    32  		p := new(int)
    33  		runtime.SetFinalizer(p, func(*int) {})
    34  
    35  		startingCycles := numGCCycles()
    36  		ch1 := make(chan *int)
    37  		ch2 := make(chan *int)
    38  		defer close(ch1)
    39  		go func() {
    40  			for i := range ch1 {
    41  				v := *i + 1
    42  				ch2 <- &v
    43  			}
    44  		}()
    45  		for {
    46  			// Make a lot of short-lived allocations to get the GC working.
    47  			for i := 0; i < 1000; i++ {
    48  				v := new(int)
    49  				*v = i
    50  				// Set finalizers on these values, just for added stress.
    51  				runtime.SetFinalizer(v, func(*int) {})
    52  				ch1 <- v
    53  				<-ch2
    54  			}
    55  
    56  			// If we've improperly put a GC goroutine into the synctest group,
    57  			// this Wait is going to hang.
    58  			synctest.Wait()
    59  
    60  			// End the test after a couple of GC cycles have passed.
    61  			if numGCCycles()-startingCycles > 1 {
    62  				break
    63  			}
    64  		}
    65  	})
    66  	println("success")
    67  }
    68  

View as plain text