Source file test/deferfin.go

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

View as plain text