...
Source file
src/runtime/semasleep_test.go
Documentation: runtime
1
2
3
4
5
6
7 package runtime_test
8
9 import (
10 "io"
11 "os/exec"
12 "syscall"
13 "testing"
14 "time"
15 )
16
17
18
19
20 func TestSpuriousWakeupsNeverHangSemasleep(t *testing.T) {
21 if *flagQuick {
22 t.Skip("-quick")
23 }
24 t.Parallel()
25
26 exe, err := buildTestProg(t, "testprog")
27 if err != nil {
28 t.Fatal(err)
29 }
30
31 cmd := exec.Command(exe, "After1")
32 stdout, err := cmd.StdoutPipe()
33 if err != nil {
34 t.Fatalf("StdoutPipe: %v", err)
35 }
36 beforeStart := time.Now()
37 if err := cmd.Start(); err != nil {
38 t.Fatalf("Failed to start command: %v", err)
39 }
40
41 waiting := false
42 doneCh := make(chan error, 1)
43 t.Cleanup(func() {
44 cmd.Process.Kill()
45 if waiting {
46 <-doneCh
47 } else {
48 cmd.Wait()
49 }
50 })
51
52
53
54 b, err := io.ReadAll(stdout)
55 if len(b) > 0 {
56 t.Logf("read from testprog stdout: %s", b)
57 }
58 if err != nil {
59 t.Fatalf("error reading from testprog: %v", err)
60 }
61
62
63
64
65
66
67
68
69 waiting = true
70 go func() {
71 doneCh <- cmd.Wait()
72 close(doneCh)
73 }()
74
75
76
77
78
79
80
81 timeout := 10 * time.Second
82
83
84
85
86 ready := time.Now()
87
88
89
90
91
92 ticker := time.NewTicker(200 * time.Millisecond)
93 defer ticker.Stop()
94 for {
95 select {
96 case now := <-ticker.C:
97 if now.Sub(ready) > timeout {
98 t.Error("Program failed to return on time and has to be killed, issue #27520 still exists")
99
100
101 cmd.Process.Signal(syscall.SIGQUIT)
102 return
103 }
104
105
106
107 cmd.Process.Signal(syscall.SIGIO)
108
109 case err := <-doneCh:
110 if err != nil {
111 t.Fatalf("The program returned but unfortunately with an error: %v", err)
112 }
113 if time.Since(beforeStart) < 1*time.Second {
114
115
116 t.Fatalf("The program stopped too quickly.")
117 }
118 return
119 }
120 }
121 }
122
View as plain text