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