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 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
64