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