mirror of
https://github.com/golang/go
synced 2024-09-04 23:44:16 +00:00
![Emmanuel Odeke](/assets/img/avatar_default.png)
Follows suit with https://go-review.googlesource.com/#/c/20111. Generated by running $ grep -R 'Go Authors. All' * | cut -d":" -f1 | while read F;do perl -pi -e 's/Go Authors. All/Go Authors. All/g' $F;done The code in cmd/internal/unvendor wasn't changed. Fixes #15213 Change-Id: I4f235cee0a62ec435f9e8540a1ec08ae03b1a75f Reviewed-on: https://go-review.googlesource.com/21819 Reviewed-by: Ian Lance Taylor <iant@golang.org> Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
92 lines
1.7 KiB
Go
92 lines
1.7 KiB
Go
// 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() {
|
|
runtime.GOMAXPROCS(1)
|
|
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")
|
|
}
|
|
}
|