aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/mcleanup_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/mcleanup_test.go')
-rw-r--r--src/runtime/mcleanup_test.go40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/runtime/mcleanup_test.go b/src/runtime/mcleanup_test.go
index d62356feef..22b9eccd20 100644
--- a/src/runtime/mcleanup_test.go
+++ b/src/runtime/mcleanup_test.go
@@ -5,8 +5,11 @@
package runtime_test
import (
+ "internal/runtime/atomic"
"runtime"
+ "sync"
"testing"
+ "time"
"unsafe"
)
@@ -296,3 +299,40 @@ func TestCleanupPointerEqualsArg(t *testing.T) {
v = nil
runtime.GC()
}
+
+// Checks to make sure cleanups aren't lost when there are a lot of them.
+func TestCleanupLost(t *testing.T) {
+ type T struct {
+ v int
+ p unsafe.Pointer
+ }
+
+ cleanups := 10_000
+ if testing.Short() {
+ cleanups = 100
+ }
+ n := runtime.GOMAXPROCS(-1)
+ want := n * cleanups
+ var got atomic.Uint64
+ var wg sync.WaitGroup
+ for i := range n {
+ wg.Add(1)
+ go func(i int) {
+ defer wg.Done()
+
+ for range cleanups {
+ v := &new(T).v
+ *v = 97531
+ runtime.AddCleanup(v, func(_ int) {
+ got.Add(1)
+ }, 97531)
+ }
+ }(i)
+ }
+ wg.Wait()
+ runtime.GC()
+ runtime.BlockUntilEmptyCleanupQueue(int64(10 * time.Second))
+ if got := int(got.Load()); got != want {
+ t.Errorf("expected %d cleanups to be executed, got %d", got, want)
+ }
+}