]> Cypherpunks.ru repositories - gostls13.git/blob - test/fixedbugs/issue9110.go
b9e861fd26a5c1c8c569e0e233e58ddf63ff4b83
[gostls13.git] / test / fixedbugs / issue9110.go
1 // run
2
3 // Copyright 2014 The Go Authors.  All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
6
7 // Scenario that used to leak arbitrarily many SudoG structs.
8 // See golang.org/issue/9110.
9
10 package main
11
12 import (
13         "runtime"
14         "runtime/debug"
15         "sync"
16         "time"
17 )
18
19 func main() {
20         runtime.GOMAXPROCS(1)
21         debug.SetGCPercent(1000000) // only GC when we ask for GC
22
23         var stats, stats1, stats2 runtime.MemStats
24
25         release := func() {}
26         for i := 0; i < 20; i++ {
27                 if i == 10 {
28                         // Should be warmed up by now.
29                         runtime.ReadMemStats(&stats1)
30                 }
31
32                 c := make(chan int)
33                 for i := 0; i < 10; i++ {
34                         go func() {
35                                 select {
36                                 case <-c:
37                                 case <-c:
38                                 case <-c:
39                                 }
40                         }()
41                 }
42                 time.Sleep(1 * time.Millisecond)
43                 release()
44
45                 close(c) // let select put its sudog's into the cache
46                 time.Sleep(1 * time.Millisecond)
47
48                 // pick up top sudog
49                 var cond1 sync.Cond
50                 var mu1 sync.Mutex
51                 cond1.L = &mu1
52                 go func() {
53                         mu1.Lock()
54                         cond1.Wait()
55                         mu1.Unlock()
56                 }()
57                 time.Sleep(1 * time.Millisecond)
58
59                 // pick up next sudog
60                 var cond2 sync.Cond
61                 var mu2 sync.Mutex
62                 cond2.L = &mu2
63                 go func() {
64                         mu2.Lock()
65                         cond2.Wait()
66                         mu2.Unlock()
67                 }()
68                 time.Sleep(1 * time.Millisecond)
69
70                 // put top sudog back
71                 cond1.Broadcast()
72                 time.Sleep(1 * time.Millisecond)
73
74                 // drop cache on floor
75                 runtime.GC()
76
77                 // release cond2 after select has gotten to run
78                 release = func() {
79                         cond2.Broadcast()
80                         time.Sleep(1 * time.Millisecond)
81                 }
82         }
83
84         runtime.GC()
85
86         runtime.ReadMemStats(&stats2)
87
88         if int(stats2.HeapObjects)-int(stats1.HeapObjects) > 20 { // normally at most 1 or 2; was 300 with leak
89                 print("BUG: object leak: ", stats.HeapObjects, " -> ", stats1.HeapObjects, " -> ", stats2.HeapObjects, "\n")
90         }
91 }