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