blob: 80372916d20b303303483f6ea36911b20482c8dc [file] [log] [blame]
Dmitriy Vyukovfd239582013-07-01 17:36:08 -04001// 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 }
Ian Lance Taylord12b08d2013-12-12 17:13:27 -080026 // Likewise for gccgo.
27 if runtime.Compiler == "gccgo" {
28 return
29 }
Dmitriy Vyukovfd239582013-07-01 17:36:08 -040030 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()
Dmitriy Vyukov1fa70292014-01-24 22:35:11 +040037 v := new(string)
Dmitriy Vyukovfd239582013-07-01 17:36:08 -040038 f := func() {
Dmitriy Vyukov1fa70292014-01-24 22:35:11 +040039 if *v != "" {
Dmitriy Vyukovfd239582013-07-01 17:36:08 -040040 panic("oops")
41 }
42 }
Dmitriy Vyukov1fa70292014-01-24 22:35:11 +040043 if *v != "" {
Dmitriy Vyukovfd239582013-07-01 17:36:08 -040044 // let the compiler think f escapes
45 sink = f
46 }
Dmitriy Vyukov1fa70292014-01-24 22:35:11 +040047 runtime.SetFinalizer(v, func(p *string) {
Dmitriy Vyukovfd239582013-07-01 17:36:08 -040048 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