Source file
src/cmd/trace/trace_unix_test.go
1
2
3
4
5
6
7
8 package main
9
10 import (
11 "bytes"
12 "cmd/internal/traceviewer"
13 traceparser "internal/trace"
14 "io"
15 "runtime"
16 "runtime/trace"
17 "sync"
18 "syscall"
19 "testing"
20 "time"
21 )
22
23
24
25
26 func TestGoroutineInSyscall(t *testing.T) {
27
28
29
30
31
32
33 var p [2]int
34 if err := syscall.Pipe(p[:]); err != nil {
35 t.Fatalf("failed to create pipe: %v", err)
36 }
37
38 var wg sync.WaitGroup
39 defer func() {
40 syscall.Write(p[1], []byte("a"))
41 wg.Wait()
42
43 syscall.Close(p[0])
44 syscall.Close(p[1])
45 }()
46 wg.Add(1)
47 go func() {
48 var tmp [1]byte
49 syscall.Read(p[0], tmp[:])
50 wg.Done()
51 }()
52
53
54 allTimers := make([]*time.Timer, 2*runtime.GOMAXPROCS(0))
55 defer func() {
56 for _, timer := range allTimers {
57 timer.Stop()
58 }
59 }()
60
61 var timerSetup sync.WaitGroup
62 for i := range allTimers {
63 timerSetup.Add(1)
64 go func(i int) {
65 defer timerSetup.Done()
66 allTimers[i] = time.AfterFunc(time.Hour, nil)
67 }(i)
68 }
69 timerSetup.Wait()
70
71
72 buf := new(bytes.Buffer)
73 if err := trace.Start(buf); err != nil {
74 t.Fatalf("failed to start tracing: %v", err)
75 }
76 trace.Stop()
77
78 res, err := traceparser.Parse(buf, "")
79 if err == traceparser.ErrTimeOrder {
80 t.Skipf("skipping due to golang.org/issue/16755 (timestamps are unreliable): %v", err)
81 } else if err != nil {
82 t.Fatalf("failed to parse trace: %v", err)
83 }
84
85
86
87 c := viewerDataTraceConsumer(io.Discard, 0, 1<<63-1)
88 c.consumeViewerEvent = func(ev *traceviewer.Event, _ bool) {
89 if ev.Name == "Threads" {
90 arg := ev.Arg.(*threadCountersArg)
91 if arg.InSyscall > 1 {
92 t.Errorf("%d threads in syscall at time %v; want less than 1 thread in syscall", arg.InSyscall, ev.Time)
93 }
94 }
95 }
96
97 param := &traceParams{
98 parsed: res,
99 endTime: int64(1<<63 - 1),
100 }
101 if err := generateTrace(param, c); err != nil {
102 t.Fatalf("failed to generate ViewerData: %v", err)
103 }
104 }
105
View as plain text