1
2
3
4
5
6
7
8 package main
9
10
29 import "C"
30
31 import (
32 "bytes"
33 "errors"
34 "fmt"
35 "io"
36 "log"
37 "net"
38 "os"
39 "os/exec"
40 "sync"
41 "syscall"
42 "time"
43 )
44
45 func init() {
46 register("EINTR", EINTR)
47 register("Block", Block)
48 }
49
50
51
52 func EINTR() {
53 if errno := C.clearRestart(C.int(syscall.SIGURG)); errno != 0 {
54 log.Fatal(syscall.Errno(errno))
55 }
56 if errno := C.clearRestart(C.int(syscall.SIGWINCH)); errno != 0 {
57 log.Fatal(syscall.Errno(errno))
58 }
59 if errno := C.clearRestart(C.int(syscall.SIGCHLD)); errno != 0 {
60 log.Fatal(syscall.Errno(errno))
61 }
62
63 var wg sync.WaitGroup
64 testPipe(&wg)
65 testNet(&wg)
66 testExec(&wg)
67 wg.Wait()
68 fmt.Println("OK")
69 }
70
71
72
73
74 func spin() (float64, []byte) {
75 stop := time.Now().Add(time.Millisecond)
76 r1 := 0.0
77 r2 := make([]byte, 200)
78 for time.Now().Before(stop) {
79 for i := 1; i < 1e6; i++ {
80 r1 += r1 / float64(i)
81 r2 = append(r2, bytes.Repeat([]byte{byte(i)}, 100)...)
82 r2 = r2[100:]
83 }
84 }
85 return r1, r2
86 }
87
88
89 func winch() {
90 ticker := time.NewTicker(100 * time.Microsecond)
91 defer ticker.Stop()
92 pid := syscall.Getpid()
93 for n := 10; n > 0; n-- {
94 syscall.Kill(pid, syscall.SIGWINCH)
95 <-ticker.C
96 }
97 }
98
99
100 func sendSomeSignals() {
101 done := make(chan struct{})
102 go func() {
103 spin()
104 close(done)
105 }()
106 winch()
107 <-done
108 }
109
110
111 func testPipe(wg *sync.WaitGroup) {
112 r, w, err := os.Pipe()
113 if err != nil {
114 log.Fatal(err)
115 }
116 if err := syscall.SetNonblock(int(r.Fd()), false); err != nil {
117 log.Fatal(err)
118 }
119 if err := syscall.SetNonblock(int(w.Fd()), false); err != nil {
120 log.Fatal(err)
121 }
122 wg.Add(2)
123 go func() {
124 defer wg.Done()
125 defer w.Close()
126
127
128
129 sendSomeSignals()
130
131
132
133
134 if _, err := w.Write(bytes.Repeat([]byte{0}, 2<<20)); err != nil {
135 log.Fatal(err)
136 }
137 }()
138 go func() {
139 defer wg.Done()
140 defer r.Close()
141 b := make([]byte, 1<<20)
142
143
144 if _, err := io.ReadFull(r, b); err != nil {
145 log.Fatal(err)
146 }
147
148
149
150 sendSomeSignals()
151 if _, err := io.ReadFull(r, b); err != nil {
152 log.Fatal(err)
153 }
154 }()
155 }
156
157
158 func testNet(wg *sync.WaitGroup) {
159 ln, err := net.Listen("tcp4", "127.0.0.1:0")
160 if err != nil {
161 if errors.Is(err, syscall.EAFNOSUPPORT) || errors.Is(err, syscall.EPROTONOSUPPORT) {
162 return
163 }
164 log.Fatal(err)
165 }
166 wg.Add(2)
167 go func() {
168 defer wg.Done()
169 defer ln.Close()
170 c, err := ln.Accept()
171 if err != nil {
172 log.Fatal(err)
173 }
174 defer c.Close()
175 cf, err := c.(*net.TCPConn).File()
176 if err != nil {
177 log.Fatal(err)
178 }
179 defer cf.Close()
180 if err := syscall.SetNonblock(int(cf.Fd()), false); err != nil {
181 log.Fatal(err)
182 }
183
184 sendSomeSignals()
185 if _, err := cf.Write(bytes.Repeat([]byte{0}, 2<<20)); err != nil {
186 log.Fatal(err)
187 }
188 }()
189 go func() {
190 defer wg.Done()
191 sendSomeSignals()
192 c, err := net.Dial("tcp", ln.Addr().String())
193 if err != nil {
194 log.Fatal(err)
195 }
196 defer c.Close()
197 cf, err := c.(*net.TCPConn).File()
198 if err != nil {
199 log.Fatal(err)
200 }
201 defer cf.Close()
202 if err := syscall.SetNonblock(int(cf.Fd()), false); err != nil {
203 log.Fatal(err)
204 }
205
206 b := make([]byte, 1<<20)
207 if _, err := io.ReadFull(cf, b); err != nil {
208 log.Fatal(err)
209 }
210 sendSomeSignals()
211 if _, err := io.ReadFull(cf, b); err != nil {
212 log.Fatal(err)
213 }
214 }()
215 }
216
217 func testExec(wg *sync.WaitGroup) {
218 wg.Add(1)
219 go func() {
220 defer wg.Done()
221 cmd := exec.Command(os.Args[0], "Block")
222 stdin, err := cmd.StdinPipe()
223 if err != nil {
224 log.Fatal(err)
225 }
226 cmd.Stderr = new(bytes.Buffer)
227 cmd.Stdout = cmd.Stderr
228 if err := cmd.Start(); err != nil {
229 log.Fatal(err)
230 }
231
232 go func() {
233 sendSomeSignals()
234 stdin.Close()
235 }()
236
237 if err := cmd.Wait(); err != nil {
238 log.Fatalf("%v:\n%s", err, cmd.Stdout)
239 }
240 }()
241 }
242
243
244 func Block() {
245 io.Copy(io.Discard, os.Stdin)
246 }
247
View as plain text