runtime_unix_test.go 1.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  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. // Only works on systems with syscall.Close.
  5. // We need a fast system call to provoke the race,
  6. // and Close(-1) is nearly universally fast.
  7. // +build darwin dragonfly freebsd linux netbsd openbsd plan9
  8. package runtime_test
  9. import (
  10. "runtime"
  11. "sync"
  12. "sync/atomic"
  13. "syscall"
  14. "testing"
  15. )
  16. func TestGoroutineProfile(t *testing.T) {
  17. // GoroutineProfile used to use the wrong starting sp for
  18. // goroutines coming out of system calls, causing possible
  19. // crashes.
  20. defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(100))
  21. var stop uint32
  22. defer atomic.StoreUint32(&stop, 1) // in case of panic
  23. var wg sync.WaitGroup
  24. for i := 0; i < 4; i++ {
  25. wg.Add(1)
  26. go func() {
  27. for atomic.LoadUint32(&stop) == 0 {
  28. syscall.Close(-1)
  29. }
  30. wg.Done()
  31. }()
  32. }
  33. max := 10000
  34. if testing.Short() {
  35. max = 100
  36. }
  37. stk := make([]runtime.StackRecord, 100)
  38. for n := 0; n < max; n++ {
  39. _, ok := runtime.GoroutineProfile(stk)
  40. if !ok {
  41. t.Fatalf("GoroutineProfile failed")
  42. }
  43. }
  44. // If the program didn't crash, we passed.
  45. atomic.StoreUint32(&stop, 1)
  46. wg.Wait()
  47. }