runtime: use small struct TestSynctest to ensure cleanups run
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>
This commit is contained in:
parent
848a768ba7
commit
985d600f3a
34
src/runtime/testdata/testsynctest/main.go
vendored
34
src/runtime/testdata/testsynctest/main.go
vendored
@ -9,6 +9,7 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"runtime/metrics"
|
"runtime/metrics"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This program ensures system goroutines (GC workers, finalizer goroutine)
|
// This program ensures system goroutines (GC workers, finalizer goroutine)
|
||||||
@ -27,6 +28,11 @@ func numGCCycles() uint64 {
|
|||||||
return samples[0].Value.Uint64()
|
return samples[0].Value.Uint64()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type T struct {
|
||||||
|
v int
|
||||||
|
p unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Channels created by a finalizer and cleanup func registered within the bubble.
|
// Channels created by a finalizer and cleanup func registered within the bubble.
|
||||||
var (
|
var (
|
||||||
@ -36,8 +42,8 @@ func main() {
|
|||||||
synctest.Run(func() {
|
synctest.Run(func() {
|
||||||
// Start the finalizer and cleanup goroutines.
|
// Start the finalizer and cleanup goroutines.
|
||||||
{
|
{
|
||||||
p := new(int)
|
p := new(T)
|
||||||
runtime.SetFinalizer(p, func(*int) {
|
runtime.SetFinalizer(p, func(*T) {
|
||||||
ch := make(chan struct{})
|
ch := make(chan struct{})
|
||||||
finalizerCh.Store(&ch)
|
finalizerCh.Store(&ch)
|
||||||
})
|
})
|
||||||
@ -47,35 +53,35 @@ func main() {
|
|||||||
}, struct{}{})
|
}, struct{}{})
|
||||||
}
|
}
|
||||||
startingCycles := numGCCycles()
|
startingCycles := numGCCycles()
|
||||||
ch1 := make(chan *int)
|
ch1 := make(chan *T)
|
||||||
ch2 := make(chan *int)
|
ch2 := make(chan *T)
|
||||||
defer close(ch1)
|
defer close(ch1)
|
||||||
go func() {
|
go func() {
|
||||||
for i := range ch1 {
|
for range ch1 {
|
||||||
v := *i + 1
|
ch2 <- &T{}
|
||||||
ch2 <- &v
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
for {
|
const iterations = 1000
|
||||||
|
for range iterations {
|
||||||
// Make a lot of short-lived allocations to get the GC working.
|
// Make a lot of short-lived allocations to get the GC working.
|
||||||
for i := 0; i < 1000; i++ {
|
for range 1000 {
|
||||||
v := new(int)
|
v := new(T)
|
||||||
*v = i
|
|
||||||
// Set finalizers on these values, just for added stress.
|
// Set finalizers on these values, just for added stress.
|
||||||
runtime.SetFinalizer(v, func(*int) {})
|
runtime.SetFinalizer(v, func(*T) {})
|
||||||
ch1 <- v
|
ch1 <- v
|
||||||
<-ch2
|
<-ch2
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we've improperly put a GC goroutine into the synctest group,
|
// If we've improperly put a GC goroutine into the synctest group,
|
||||||
// this Wait is going to hang.
|
// this Wait is going to hang.
|
||||||
//synctest.Wait()
|
synctest.Wait()
|
||||||
|
|
||||||
// End the test after a couple of GC cycles have passed.
|
// End the test after a couple of GC cycles have passed.
|
||||||
if numGCCycles()-startingCycles > 1 && finalizerCh.Load() != nil && cleanupCh.Load() != nil {
|
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.
|
// Close the channels created by the finalizer and cleanup func.
|
||||||
// If the funcs improperly ran inside the bubble, these channels are bubbled
|
// If the funcs improperly ran inside the bubble, these channels are bubbled
|
||||||
|
Loading…
x
Reference in New Issue
Block a user