1// run 2 3// Copyright 2013 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// Test that defers do not prevent garbage collection. 8 9package main 10 11import ( 12 "runtime" 13 "sync" 14 "sync/atomic" 15 "time" 16) 17 18var sink func() 19 20func main() { 21 // Does not work with gccgo, due to partially conservative GC. 22 // Try to enable when we have fully precise GC. 23 if runtime.Compiler == "gccgo" { 24 return 25 } 26 N := 10 27 count := int32(N) 28 var wg sync.WaitGroup 29 wg.Add(N) 30 for i := 0; i < N; i++ { 31 go func() { 32 defer wg.Done() 33 v := new(string) 34 f := func() { 35 if *v != "" { 36 panic("oops") 37 } 38 } 39 if *v != "" { 40 // let the compiler think f escapes 41 sink = f 42 } 43 runtime.SetFinalizer(v, func(p *string) { 44 atomic.AddInt32(&count, -1) 45 }) 46 defer f() 47 }() 48 } 49 wg.Wait() 50 for i := 0; i < 3; i++ { 51 time.Sleep(10 * time.Millisecond) 52 runtime.GC() 53 } 54 if count != 0 { 55 println(count, "out of", N, "finalizer are not called") 56 panic("not all finalizers are called") 57 } 58} 59