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