1
2
3
4
5
6
7
8 package poll
9
10 import (
11 "io"
12 "sync/atomic"
13 "syscall"
14 )
15
16
17
18 type FD struct {
19
20 fdmu fdMutex
21
22
23 Sysfd int
24
25
26 pd pollDesc
27
28
29 iovecs *[]syscall.Iovec
30
31
32 csema uint32
33
34
35 isBlocking uint32
36
37
38
39 IsStream bool
40
41
42
43 ZeroReadIsEOF bool
44
45
46 isFile bool
47 }
48
49
50
51
52
53
54 func (fd *FD) Init(net string, pollable bool) error {
55
56 if net == "file" {
57 fd.isFile = true
58 }
59 if !pollable {
60 fd.isBlocking = 1
61 return nil
62 }
63 err := fd.pd.init(fd)
64 if err != nil {
65
66
67 fd.isBlocking = 1
68 }
69 return err
70 }
71
72
73
74 func (fd *FD) destroy() error {
75
76
77 fd.pd.close()
78
79
80
81
82
83
84 err := CloseFunc(fd.Sysfd)
85
86 fd.Sysfd = -1
87 runtime_Semrelease(&fd.csema)
88 return err
89 }
90
91
92
93 func (fd *FD) Close() error {
94 if !fd.fdmu.increfAndClose() {
95 return errClosing(fd.isFile)
96 }
97
98
99
100
101
102
103 fd.pd.evict()
104
105
106
107 err := fd.decref()
108
109
110
111
112
113
114
115 if fd.isBlocking == 0 {
116 runtime_Semacquire(&fd.csema)
117 }
118
119 return err
120 }
121
122
123 func (fd *FD) SetBlocking() error {
124 if err := fd.incref(); err != nil {
125 return err
126 }
127 defer fd.decref()
128
129
130
131 atomic.StoreUint32(&fd.isBlocking, 1)
132 return syscall.SetNonblock(fd.Sysfd, false)
133 }
134
135
136
137
138
139
140 const maxRW = 1 << 30
141
142
143 func (fd *FD) Read(p []byte) (int, error) {
144 if err := fd.readLock(); err != nil {
145 return 0, err
146 }
147 defer fd.readUnlock()
148 if len(p) == 0 {
149
150
151
152
153
154 return 0, nil
155 }
156 if err := fd.pd.prepareRead(fd.isFile); err != nil {
157 return 0, err
158 }
159 if fd.IsStream && len(p) > maxRW {
160 p = p[:maxRW]
161 }
162 for {
163 n, err := ignoringEINTRIO(syscall.Read, fd.Sysfd, p)
164 if err != nil {
165 n = 0
166 if err == syscall.EAGAIN && fd.pd.pollable() {
167 if err = fd.pd.waitRead(fd.isFile); err == nil {
168 continue
169 }
170 }
171 }
172 err = fd.eofError(n, err)
173 return n, err
174 }
175 }
176
177
178 func (fd *FD) Pread(p []byte, off int64) (int, error) {
179
180
181
182 if err := fd.incref(); err != nil {
183 return 0, err
184 }
185 if fd.IsStream && len(p) > maxRW {
186 p = p[:maxRW]
187 }
188 var (
189 n int
190 err error
191 )
192 for {
193 n, err = syscall.Pread(fd.Sysfd, p, off)
194 if err != syscall.EINTR {
195 break
196 }
197 }
198 if err != nil {
199 n = 0
200 }
201 fd.decref()
202 err = fd.eofError(n, err)
203 return n, err
204 }
205
206
207 func (fd *FD) ReadFrom(p []byte) (int, syscall.Sockaddr, error) {
208 if err := fd.readLock(); err != nil {
209 return 0, nil, err
210 }
211 defer fd.readUnlock()
212 if err := fd.pd.prepareRead(fd.isFile); err != nil {
213 return 0, nil, err
214 }
215 for {
216 n, sa, err := syscall.Recvfrom(fd.Sysfd, p, 0)
217 if err != nil {
218 if err == syscall.EINTR {
219 continue
220 }
221 n = 0
222 if err == syscall.EAGAIN && fd.pd.pollable() {
223 if err = fd.pd.waitRead(fd.isFile); err == nil {
224 continue
225 }
226 }
227 }
228 err = fd.eofError(n, err)
229 return n, sa, err
230 }
231 }
232
233
234 func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) {
235 if err := fd.readLock(); err != nil {
236 return 0, 0, 0, nil, err
237 }
238 defer fd.readUnlock()
239 if err := fd.pd.prepareRead(fd.isFile); err != nil {
240 return 0, 0, 0, nil, err
241 }
242 for {
243 n, oobn, sysflags, sa, err := syscall.Recvmsg(fd.Sysfd, p, oob, flags)
244 if err != nil {
245 if err == syscall.EINTR {
246 continue
247 }
248
249 if err == syscall.EAGAIN && fd.pd.pollable() {
250 if err = fd.pd.waitRead(fd.isFile); err == nil {
251 continue
252 }
253 }
254 }
255 err = fd.eofError(n, err)
256 return n, oobn, sysflags, sa, err
257 }
258 }
259
260
261 func (fd *FD) Write(p []byte) (int, error) {
262 if err := fd.writeLock(); err != nil {
263 return 0, err
264 }
265 defer fd.writeUnlock()
266 if err := fd.pd.prepareWrite(fd.isFile); err != nil {
267 return 0, err
268 }
269 var nn int
270 for {
271 max := len(p)
272 if fd.IsStream && max-nn > maxRW {
273 max = nn + maxRW
274 }
275 n, err := ignoringEINTRIO(syscall.Write, fd.Sysfd, p[nn:max])
276 if n > 0 {
277 nn += n
278 }
279 if nn == len(p) {
280 return nn, err
281 }
282 if err == syscall.EAGAIN && fd.pd.pollable() {
283 if err = fd.pd.waitWrite(fd.isFile); err == nil {
284 continue
285 }
286 }
287 if err != nil {
288 return nn, err
289 }
290 if n == 0 {
291 return nn, io.ErrUnexpectedEOF
292 }
293 }
294 }
295
296
297 func (fd *FD) Pwrite(p []byte, off int64) (int, error) {
298
299
300
301 if err := fd.incref(); err != nil {
302 return 0, err
303 }
304 defer fd.decref()
305 var nn int
306 for {
307 max := len(p)
308 if fd.IsStream && max-nn > maxRW {
309 max = nn + maxRW
310 }
311 n, err := syscall.Pwrite(fd.Sysfd, p[nn:max], off+int64(nn))
312 if err == syscall.EINTR {
313 continue
314 }
315 if n > 0 {
316 nn += n
317 }
318 if nn == len(p) {
319 return nn, err
320 }
321 if err != nil {
322 return nn, err
323 }
324 if n == 0 {
325 return nn, io.ErrUnexpectedEOF
326 }
327 }
328 }
329
330
331 func (fd *FD) WriteTo(p []byte, sa syscall.Sockaddr) (int, error) {
332 if err := fd.writeLock(); err != nil {
333 return 0, err
334 }
335 defer fd.writeUnlock()
336 if err := fd.pd.prepareWrite(fd.isFile); err != nil {
337 return 0, err
338 }
339 for {
340 err := syscall.Sendto(fd.Sysfd, p, 0, sa)
341 if err == syscall.EINTR {
342 continue
343 }
344 if err == syscall.EAGAIN && fd.pd.pollable() {
345 if err = fd.pd.waitWrite(fd.isFile); err == nil {
346 continue
347 }
348 }
349 if err != nil {
350 return 0, err
351 }
352 return len(p), nil
353 }
354 }
355
356
357 func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, error) {
358 if err := fd.writeLock(); err != nil {
359 return 0, 0, err
360 }
361 defer fd.writeUnlock()
362 if err := fd.pd.prepareWrite(fd.isFile); err != nil {
363 return 0, 0, err
364 }
365 for {
366 n, err := syscall.SendmsgN(fd.Sysfd, p, oob, sa, 0)
367 if err == syscall.EINTR {
368 continue
369 }
370 if err == syscall.EAGAIN && fd.pd.pollable() {
371 if err = fd.pd.waitWrite(fd.isFile); err == nil {
372 continue
373 }
374 }
375 if err != nil {
376 return n, 0, err
377 }
378 return n, len(oob), err
379 }
380 }
381
382
383 func (fd *FD) Accept() (int, syscall.Sockaddr, string, error) {
384 if err := fd.readLock(); err != nil {
385 return -1, nil, "", err
386 }
387 defer fd.readUnlock()
388
389 if err := fd.pd.prepareRead(fd.isFile); err != nil {
390 return -1, nil, "", err
391 }
392 for {
393 s, rsa, errcall, err := accept(fd.Sysfd)
394 if err == nil {
395 return s, rsa, "", err
396 }
397 switch err {
398 case syscall.EINTR:
399 continue
400 case syscall.EAGAIN:
401 if fd.pd.pollable() {
402 if err = fd.pd.waitRead(fd.isFile); err == nil {
403 continue
404 }
405 }
406 case syscall.ECONNABORTED:
407
408
409
410 continue
411 }
412 return -1, nil, errcall, err
413 }
414 }
415
416
417 func (fd *FD) Seek(offset int64, whence int) (int64, error) {
418 if err := fd.incref(); err != nil {
419 return 0, err
420 }
421 defer fd.decref()
422 return syscall.Seek(fd.Sysfd, offset, whence)
423 }
424
425
426
427
428 func (fd *FD) ReadDirent(buf []byte) (int, error) {
429 if err := fd.incref(); err != nil {
430 return 0, err
431 }
432 defer fd.decref()
433 for {
434 n, err := ignoringEINTRIO(syscall.ReadDirent, fd.Sysfd, buf)
435 if err != nil {
436 n = 0
437 if err == syscall.EAGAIN && fd.pd.pollable() {
438 if err = fd.pd.waitRead(fd.isFile); err == nil {
439 continue
440 }
441 }
442 }
443
444 return n, err
445 }
446 }
447
448
449 func (fd *FD) Fchmod(mode uint32) error {
450 if err := fd.incref(); err != nil {
451 return err
452 }
453 defer fd.decref()
454 return ignoringEINTR(func() error {
455 return syscall.Fchmod(fd.Sysfd, mode)
456 })
457 }
458
459
460 func (fd *FD) Fchdir() error {
461 if err := fd.incref(); err != nil {
462 return err
463 }
464 defer fd.decref()
465 return syscall.Fchdir(fd.Sysfd)
466 }
467
468
469 func (fd *FD) Fstat(s *syscall.Stat_t) error {
470 if err := fd.incref(); err != nil {
471 return err
472 }
473 defer fd.decref()
474 return ignoringEINTR(func() error {
475 return syscall.Fstat(fd.Sysfd, s)
476 })
477 }
478
479
480
481 var tryDupCloexec = int32(1)
482
483
484 func DupCloseOnExec(fd int) (int, string, error) {
485 if syscall.F_DUPFD_CLOEXEC != 0 && atomic.LoadInt32(&tryDupCloexec) == 1 {
486 r0, e1 := fcntl(fd, syscall.F_DUPFD_CLOEXEC, 0)
487 if e1 == nil {
488 return r0, "", nil
489 }
490 switch e1.(syscall.Errno) {
491 case syscall.EINVAL, syscall.ENOSYS:
492
493
494
495 atomic.StoreInt32(&tryDupCloexec, 0)
496 default:
497 return -1, "fcntl", e1
498 }
499 }
500 return dupCloseOnExecOld(fd)
501 }
502
503
504
505 func dupCloseOnExecOld(fd int) (int, string, error) {
506 syscall.ForkLock.RLock()
507 defer syscall.ForkLock.RUnlock()
508 newfd, err := syscall.Dup(fd)
509 if err != nil {
510 return -1, "dup", err
511 }
512 syscall.CloseOnExec(newfd)
513 return newfd, "", nil
514 }
515
516
517 func (fd *FD) Dup() (int, string, error) {
518 if err := fd.incref(); err != nil {
519 return -1, "", err
520 }
521 defer fd.decref()
522 return DupCloseOnExec(fd.Sysfd)
523 }
524
525
526
527
528 func (fd *FD) WaitWrite() error {
529 return fd.pd.waitWrite(fd.isFile)
530 }
531
532
533 func (fd *FD) WriteOnce(p []byte) (int, error) {
534 if err := fd.writeLock(); err != nil {
535 return 0, err
536 }
537 defer fd.writeUnlock()
538 return ignoringEINTRIO(syscall.Write, fd.Sysfd, p)
539 }
540
541
542 func (fd *FD) RawRead(f func(uintptr) bool) error {
543 if err := fd.readLock(); err != nil {
544 return err
545 }
546 defer fd.readUnlock()
547 if err := fd.pd.prepareRead(fd.isFile); err != nil {
548 return err
549 }
550 for {
551 if f(uintptr(fd.Sysfd)) {
552 return nil
553 }
554 if err := fd.pd.waitRead(fd.isFile); err != nil {
555 return err
556 }
557 }
558 }
559
560
561 func (fd *FD) RawWrite(f func(uintptr) bool) error {
562 if err := fd.writeLock(); err != nil {
563 return err
564 }
565 defer fd.writeUnlock()
566 if err := fd.pd.prepareWrite(fd.isFile); err != nil {
567 return err
568 }
569 for {
570 if f(uintptr(fd.Sysfd)) {
571 return nil
572 }
573 if err := fd.pd.waitWrite(fd.isFile); err != nil {
574 return err
575 }
576 }
577 }
578
579
580 func ignoringEINTRIO(fn func(fd int, p []byte) (int, error), fd int, p []byte) (int, error) {
581 for {
582 n, err := fn(fd, p)
583 if err != syscall.EINTR {
584 return n, err
585 }
586 }
587 }
588
View as plain text