Home | History | Annotate | Download | only in runtime
      1 // Copyright 2013 The Go Authors.  All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // Only works on systems with syscall.Close.
      6 // We need a fast system call to provoke the race,
      7 // and Close(-1) is nearly universally fast.
      8 
      9 // +build darwin dragonfly freebsd linux netbsd openbsd plan9
     10 
     11 package runtime_test
     12 
     13 import (
     14 	"runtime"
     15 	"sync"
     16 	"sync/atomic"
     17 	"syscall"
     18 	"testing"
     19 )
     20 
     21 func TestGoroutineProfile(t *testing.T) {
     22 	// GoroutineProfile used to use the wrong starting sp for
     23 	// goroutines coming out of system calls, causing possible
     24 	// crashes.
     25 	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(100))
     26 
     27 	var stop uint32
     28 	defer atomic.StoreUint32(&stop, 1) // in case of panic
     29 
     30 	var wg sync.WaitGroup
     31 	for i := 0; i < 4; i++ {
     32 		wg.Add(1)
     33 		go func() {
     34 			for atomic.LoadUint32(&stop) == 0 {
     35 				syscall.Close(-1)
     36 			}
     37 			wg.Done()
     38 		}()
     39 	}
     40 
     41 	max := 10000
     42 	if testing.Short() {
     43 		max = 100
     44 	}
     45 	stk := make([]runtime.StackRecord, 128)
     46 	for n := 0; n < max; n++ {
     47 		_, ok := runtime.GoroutineProfile(stk)
     48 		if !ok {
     49 			t.Fatalf("GoroutineProfile failed")
     50 		}
     51 	}
     52 
     53 	// If the program didn't crash, we passed.
     54 	atomic.StoreUint32(&stop, 1)
     55 	wg.Wait()
     56 }
     57