diff options
author | Russ Cox <rsc@golang.org> | 2014-11-24 12:07:11 -0500 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2014-11-24 12:07:11 -0500 |
commit | e5fc9ffb729e31c4eb0a6518e819e9fc70f14818 (patch) | |
tree | 5f67f9fb6c209085505b8fa6a01a245942ea45c3 /test | |
parent | df7d4576f312e1b646af4f5f1a32412a4221b785 (diff) | |
parent | db6a11ff558add790779fdef118b5ad899f77137 (diff) | |
download | go-e5fc9ffb729e31c4eb0a6518e819e9fc70f14818.tar.gz |
[dev.garbage] all: merge dev.cc (493ad916c3b1) into dev.garbage
TBR=austin
CC=golang-codereviews
https://codereview.appspot.com/179290043
Diffstat (limited to 'test')
-rw-r--r-- | test/fixedbugs/issue9110.go | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/test/fixedbugs/issue9110.go b/test/fixedbugs/issue9110.go new file mode 100644 index 000000000..729463305 --- /dev/null +++ b/test/fixedbugs/issue9110.go @@ -0,0 +1,90 @@ +// run + +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Scenario that used to leak arbitrarily many SudoG structs. +// See golang.org/issue/9110. + +package main + +import ( + "runtime" + "runtime/debug" + "sync" + "time" +) + +func main() { + debug.SetGCPercent(1000000) // only GC when we ask for GC + + var stats, stats1, stats2 runtime.MemStats + + release := func() {} + for i := 0; i < 20; i++ { + if i == 10 { + // Should be warmed up by now. + runtime.ReadMemStats(&stats1) + } + + c := make(chan int) + for i := 0; i < 10; i++ { + go func() { + select { + case <-c: + case <-c: + case <-c: + } + }() + } + time.Sleep(1 * time.Millisecond) + release() + + close(c) // let select put its sudog's into the cache + time.Sleep(1 * time.Millisecond) + + // pick up top sudog + var cond1 sync.Cond + var mu1 sync.Mutex + cond1.L = &mu1 + go func() { + mu1.Lock() + cond1.Wait() + mu1.Unlock() + }() + time.Sleep(1 * time.Millisecond) + + // pick up next sudog + var cond2 sync.Cond + var mu2 sync.Mutex + cond2.L = &mu2 + go func() { + mu2.Lock() + cond2.Wait() + mu2.Unlock() + }() + time.Sleep(1 * time.Millisecond) + + // put top sudog back + cond1.Broadcast() + time.Sleep(1 * time.Millisecond) + + // drop cache on floor + runtime.GC() + + // release cond2 after select has gotten to run + release = func() { + cond2.Broadcast() + time.Sleep(1 * time.Millisecond) + } + } + + runtime.GC() + + runtime.ReadMemStats(&stats2) + + if int(stats2.HeapObjects)-int(stats1.HeapObjects) > 20 { // normally at most 1 or 2; was 300 with leak + print("BUG: object leak: ", stats.HeapObjects, " -> ", stats1.HeapObjects, " -> ", stats2.HeapObjects, "\n") + } +} |