Home | History | Annotate | Download | only in test
      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 
     64