1
2
3
4
5
6
7 package poll
8
9 import (
10 "internal/itoa"
11 "internal/syscall/unix"
12 "io"
13 "sync/atomic"
14 "syscall"
15 )
16
17
18
19 type FD struct {
20
21 fdmu fdMutex
22
23
24 Sysfd int
25
26
27 SysFile
28
29
30 pd pollDesc
31
32
33 csema uint32
34
35
36 isBlocking uint32
37
38
39
40 IsStream bool
41
42
43
44 ZeroReadIsEOF bool
45
46
47 isFile bool
48 }
49
50
51
52
53
54
55 func (fd *FD) Init(net string, pollable bool) error {
56 fd.SysFile.init()
57
58
59 if net == "file" {
60 fd.isFile = true
61 }
62 if !pollable {
63 fd.isBlocking = 1
64 return nil
65 }
66 err := fd.pd.init(fd)
67 if err != nil {
68
69
70 fd.isBlocking = 1
71 }
72 return err
73 }
74
75
76
77 func (fd *FD) destroy() error {
78
79
80 fd.pd.close()
81
82 err := fd.SysFile.destroy(fd.Sysfd)
83
84 fd.Sysfd = -1
85 runtime_Semrelease(&fd.csema)
86 return err
87 }
88
89
90
91 func (fd *FD) Close() error {
92 if !fd.fdmu.increfAndClose() {
93 return errClosing(fd.isFile)
94 }
95
96
97
98
99
100
101 fd.pd.evict()
102
103
104
105 err := fd.decref()
106
107
108
109
110
111
112
113 if fd.isBlocking == 0 {
114 runtime_Semacquire(&fd.csema)
115 }
116
117 return err
118 }
119
120
121 func (fd *FD) SetBlocking() error {
122 if err := fd.incref(); err != nil {
123 return err
124 }
125 defer fd.decref()
126
127
128
129 atomic.StoreUint32(&fd.isBlocking, 1)
130 return syscall.SetNonblock(fd.Sysfd, false)
131 }
132
133
134
135
136
137
138 const maxRW = 1 << 30
139
140
141 func (fd *FD) Read(p []byte) (int, error) {
142 if err := fd.readLock(); err != nil {
143 return 0, err
144 }
145 defer fd.readUnlock()
146 if len(p) == 0 {
147
148
149
150
151
152 return 0, nil
153 }
154 if err := fd.pd.prepareRead(fd.isFile); err != nil {
155 return 0, err
156 }
157 if fd.IsStream && len(p) > maxRW {
158 p = p[:maxRW]
159 }
160 for {
161 n, err := ignoringEINTRIO(syscall.Read, fd.Sysfd, p)
162 if err != nil {
163 n = 0
164 if err == syscall.EAGAIN && fd.pd.pollable() {
165 if err = fd.pd.waitRead(fd.isFile); err == nil {
166 continue
167 }
168 }
169 }
170 err = fd.eofError(n, err)
171 return n, err
172 }
173 }
174
175
176 func (fd *FD) Pread(p []byte, off int64) (int, error) {
177
178
179
180 if err := fd.incref(); err != nil {
181 return 0, err
182 }
183 if fd.IsStream && len(p) > maxRW {
184 p = p[:maxRW]
185 }
186 n, err := ignoringEINTR2(func() (int, error) {
187 return syscall.Pread(fd.Sysfd, p, off)
188 })
189 if err != nil {
190 n = 0
191 }
192 fd.decref()
193 err = fd.eofError(n, err)
194 return n, err
195 }
196
197
198 func (fd *FD) ReadFrom(p []byte) (int, syscall.Sockaddr, error) {
199 if err := fd.readLock(); err != nil {
200 return 0, nil, err
201 }
202 defer fd.readUnlock()
203 if err := fd.pd.prepareRead(fd.isFile); err != nil {
204 return 0, nil, err
205 }
206 for {
207 n, sa, err := syscall.Recvfrom(fd.Sysfd, p, 0)
208 if err != nil {
209 if err == syscall.EINTR {
210 continue
211 }
212 n = 0
213 if err == syscall.EAGAIN && fd.pd.pollable() {
214 if err = fd.pd.waitRead(fd.isFile); err == nil {
215 continue
216 }
217 }
218 }
219 err = fd.eofError(n, err)
220 return n, sa, err
221 }
222 }
223
224
225 func (fd *FD) ReadFromInet4(p []byte, from *syscall.SockaddrInet4) (int, error) {
226 if err := fd.readLock(); err != nil {
227 return 0, err
228 }
229 defer fd.readUnlock()
230 if err := fd.pd.prepareRead(fd.isFile); err != nil {
231 return 0, err
232 }
233 for {
234 n, err := unix.RecvfromInet4(fd.Sysfd, p, 0, from)
235 if err != nil {
236 if err == syscall.EINTR {
237 continue
238 }
239 n = 0
240 if err == syscall.EAGAIN && fd.pd.pollable() {
241 if err = fd.pd.waitRead(fd.isFile); err == nil {
242 continue
243 }
244 }
245 }
246 err = fd.eofError(n, err)
247 return n, err
248 }
249 }
250
251
252 func (fd *FD) ReadFromInet6(p []byte, from *syscall.SockaddrInet6) (int, error) {
253 if err := fd.readLock(); err != nil {
254 return 0, err
255 }
256 defer fd.readUnlock()
257 if err := fd.pd.prepareRead(fd.isFile); err != nil {
258 return 0, err
259 }
260 for {
261 n, err := unix.RecvfromInet6(fd.Sysfd, p, 0, from)
262 if err != nil {
263 if err == syscall.EINTR {
264 continue
265 }
266 n = 0
267 if err == syscall.EAGAIN && fd.pd.pollable() {
268 if err = fd.pd.waitRead(fd.isFile); err == nil {
269 continue
270 }
271 }
272 }
273 err = fd.eofError(n, err)
274 return n, err
275 }
276 }
277
278
279 func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) {
280 if err := fd.readLock(); err != nil {
281 return 0, 0, 0, nil, err
282 }
283 defer fd.readUnlock()
284 if err := fd.pd.prepareRead(fd.isFile); err != nil {
285 return 0, 0, 0, nil, err
286 }
287 for {
288 n, oobn, sysflags, sa, err := syscall.Recvmsg(fd.Sysfd, p, oob, flags)
289 if err != nil {
290 if err == syscall.EINTR {
291 continue
292 }
293
294 if err == syscall.EAGAIN && fd.pd.pollable() {
295 if err = fd.pd.waitRead(fd.isFile); err == nil {
296 continue
297 }
298 }
299 }
300 err = fd.eofError(n, err)
301 return n, oobn, sysflags, sa, err
302 }
303 }
304
305
306 func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.SockaddrInet4) (int, int, int, error) {
307 if err := fd.readLock(); err != nil {
308 return 0, 0, 0, err
309 }
310 defer fd.readUnlock()
311 if err := fd.pd.prepareRead(fd.isFile); err != nil {
312 return 0, 0, 0, err
313 }
314 for {
315 n, oobn, sysflags, err := unix.RecvmsgInet4(fd.Sysfd, p, oob, flags, sa4)
316 if err != nil {
317 if err == syscall.EINTR {
318 continue
319 }
320
321 if err == syscall.EAGAIN && fd.pd.pollable() {
322 if err = fd.pd.waitRead(fd.isFile); err == nil {
323 continue
324 }
325 }
326 }
327 err = fd.eofError(n, err)
328 return n, oobn, sysflags, err
329 }
330 }
331
332
333 func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.SockaddrInet6) (int, int, int, error) {
334 if err := fd.readLock(); err != nil {
335 return 0, 0, 0, err
336 }
337 defer fd.readUnlock()
338 if err := fd.pd.prepareRead(fd.isFile); err != nil {
339 return 0, 0, 0, err
340 }
341 for {
342 n, oobn, sysflags, err := unix.RecvmsgInet6(fd.Sysfd, p, oob, flags, sa6)
343 if err != nil {
344 if err == syscall.EINTR {
345 continue
346 }
347
348 if err == syscall.EAGAIN && fd.pd.pollable() {
349 if err = fd.pd.waitRead(fd.isFile); err == nil {
350 continue
351 }
352 }
353 }
354 err = fd.eofError(n, err)
355 return n, oobn, sysflags, err
356 }
357 }
358
359
360 func (fd *FD) Write(p []byte) (int, error) {
361 if err := fd.writeLock(); err != nil {
362 return 0, err
363 }
364 defer fd.writeUnlock()
365 if err := fd.pd.prepareWrite(fd.isFile); err != nil {
366 return 0, err
367 }
368 var nn int
369 for {
370 max := len(p)
371 if fd.IsStream && max-nn > maxRW {
372 max = nn + maxRW
373 }
374 n, err := ignoringEINTRIO(syscall.Write, fd.Sysfd, p[nn:max])
375 if n > 0 {
376 if n > max-nn {
377
378
379
380
381
382 panic("invalid return from write: got " + itoa.Itoa(n) + " from a write of " + itoa.Itoa(max-nn))
383 }
384 nn += n
385 }
386 if nn == len(p) {
387 return nn, err
388 }
389 if err == syscall.EAGAIN && fd.pd.pollable() {
390 if err = fd.pd.waitWrite(fd.isFile); err == nil {
391 continue
392 }
393 }
394 if err != nil {
395 return nn, err
396 }
397 if n == 0 {
398 return nn, io.ErrUnexpectedEOF
399 }
400 }
401 }
402
403
404 func (fd *FD) Pwrite(p []byte, off int64) (int, error) {
405
406
407
408 if err := fd.incref(); err != nil {
409 return 0, err
410 }
411 defer fd.decref()
412 var nn int
413 for {
414 max := len(p)
415 if fd.IsStream && max-nn > maxRW {
416 max = nn + maxRW
417 }
418 n, err := syscall.Pwrite(fd.Sysfd, p[nn:max], off+int64(nn))
419 if err == syscall.EINTR {
420 continue
421 }
422 if n > 0 {
423 nn += n
424 }
425 if nn == len(p) {
426 return nn, err
427 }
428 if err != nil {
429 return nn, err
430 }
431 if n == 0 {
432 return nn, io.ErrUnexpectedEOF
433 }
434 }
435 }
436
437
438 func (fd *FD) WriteToInet4(p []byte, sa *syscall.SockaddrInet4) (int, error) {
439 if err := fd.writeLock(); err != nil {
440 return 0, err
441 }
442 defer fd.writeUnlock()
443 if err := fd.pd.prepareWrite(fd.isFile); err != nil {
444 return 0, err
445 }
446 for {
447 err := unix.SendtoInet4(fd.Sysfd, p, 0, sa)
448 if err == syscall.EINTR {
449 continue
450 }
451 if err == syscall.EAGAIN && fd.pd.pollable() {
452 if err = fd.pd.waitWrite(fd.isFile); err == nil {
453 continue
454 }
455 }
456 if err != nil {
457 return 0, err
458 }
459 return len(p), nil
460 }
461 }
462
463
464 func (fd *FD) WriteToInet6(p []byte, sa *syscall.SockaddrInet6) (int, error) {
465 if err := fd.writeLock(); err != nil {
466 return 0, err
467 }
468 defer fd.writeUnlock()
469 if err := fd.pd.prepareWrite(fd.isFile); err != nil {
470 return 0, err
471 }
472 for {
473 err := unix.SendtoInet6(fd.Sysfd, p, 0, sa)
474 if err == syscall.EINTR {
475 continue
476 }
477 if err == syscall.EAGAIN && fd.pd.pollable() {
478 if err = fd.pd.waitWrite(fd.isFile); err == nil {
479 continue
480 }
481 }
482 if err != nil {
483 return 0, err
484 }
485 return len(p), nil
486 }
487 }
488
489
490 func (fd *FD) WriteTo(p []byte, sa syscall.Sockaddr) (int, error) {
491 if err := fd.writeLock(); err != nil {
492 return 0, err
493 }
494 defer fd.writeUnlock()
495 if err := fd.pd.prepareWrite(fd.isFile); err != nil {
496 return 0, err
497 }
498 for {
499 err := syscall.Sendto(fd.Sysfd, p, 0, sa)
500 if err == syscall.EINTR {
501 continue
502 }
503 if err == syscall.EAGAIN && fd.pd.pollable() {
504 if err = fd.pd.waitWrite(fd.isFile); err == nil {
505 continue
506 }
507 }
508 if err != nil {
509 return 0, err
510 }
511 return len(p), nil
512 }
513 }
514
515
516 func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, error) {
517 if err := fd.writeLock(); err != nil {
518 return 0, 0, err
519 }
520 defer fd.writeUnlock()
521 if err := fd.pd.prepareWrite(fd.isFile); err != nil {
522 return 0, 0, err
523 }
524 for {
525 n, err := syscall.SendmsgN(fd.Sysfd, p, oob, sa, 0)
526 if err == syscall.EINTR {
527 continue
528 }
529 if err == syscall.EAGAIN && fd.pd.pollable() {
530 if err = fd.pd.waitWrite(fd.isFile); err == nil {
531 continue
532 }
533 }
534 if err != nil {
535 return n, 0, err
536 }
537 return n, len(oob), err
538 }
539 }
540
541
542 func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (int, int, error) {
543 if err := fd.writeLock(); err != nil {
544 return 0, 0, err
545 }
546 defer fd.writeUnlock()
547 if err := fd.pd.prepareWrite(fd.isFile); err != nil {
548 return 0, 0, err
549 }
550 for {
551 n, err := unix.SendmsgNInet4(fd.Sysfd, p, oob, sa, 0)
552 if err == syscall.EINTR {
553 continue
554 }
555 if err == syscall.EAGAIN && fd.pd.pollable() {
556 if err = fd.pd.waitWrite(fd.isFile); err == nil {
557 continue
558 }
559 }
560 if err != nil {
561 return n, 0, err
562 }
563 return n, len(oob), err
564 }
565 }
566
567
568 func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (int, int, error) {
569 if err := fd.writeLock(); err != nil {
570 return 0, 0, err
571 }
572 defer fd.writeUnlock()
573 if err := fd.pd.prepareWrite(fd.isFile); err != nil {
574 return 0, 0, err
575 }
576 for {
577 n, err := unix.SendmsgNInet6(fd.Sysfd, p, oob, sa, 0)
578 if err == syscall.EINTR {
579 continue
580 }
581 if err == syscall.EAGAIN && fd.pd.pollable() {
582 if err = fd.pd.waitWrite(fd.isFile); err == nil {
583 continue
584 }
585 }
586 if err != nil {
587 return n, 0, err
588 }
589 return n, len(oob), err
590 }
591 }
592
593
594 func (fd *FD) Accept() (int, syscall.Sockaddr, string, error) {
595 if err := fd.readLock(); err != nil {
596 return -1, nil, "", err
597 }
598 defer fd.readUnlock()
599
600 if err := fd.pd.prepareRead(fd.isFile); err != nil {
601 return -1, nil, "", err
602 }
603 for {
604 s, rsa, errcall, err := accept(fd.Sysfd)
605 if err == nil {
606 return s, rsa, "", err
607 }
608 switch err {
609 case syscall.EINTR:
610 continue
611 case syscall.EAGAIN:
612 if fd.pd.pollable() {
613 if err = fd.pd.waitRead(fd.isFile); err == nil {
614 continue
615 }
616 }
617 case syscall.ECONNABORTED:
618
619
620
621 continue
622 }
623 return -1, nil, errcall, err
624 }
625 }
626
627
628 func (fd *FD) Fchmod(mode uint32) error {
629 if err := fd.incref(); err != nil {
630 return err
631 }
632 defer fd.decref()
633 return ignoringEINTR(func() error {
634 return syscall.Fchmod(fd.Sysfd, mode)
635 })
636 }
637
638
639 func (fd *FD) Fstat(s *syscall.Stat_t) error {
640 if err := fd.incref(); err != nil {
641 return err
642 }
643 defer fd.decref()
644 return ignoringEINTR(func() error {
645 return syscall.Fstat(fd.Sysfd, s)
646 })
647 }
648
649
650 var dupCloexecUnsupported atomic.Bool
651
652
653 func DupCloseOnExec(fd int) (int, string, error) {
654 if syscall.F_DUPFD_CLOEXEC != 0 && !dupCloexecUnsupported.Load() {
655 r0, err := unix.Fcntl(fd, syscall.F_DUPFD_CLOEXEC, 0)
656 if err == nil {
657 return r0, "", nil
658 }
659 switch err {
660 case syscall.EINVAL, syscall.ENOSYS:
661
662
663
664 dupCloexecUnsupported.Store(true)
665 default:
666 return -1, "fcntl", err
667 }
668 }
669 return dupCloseOnExecOld(fd)
670 }
671
672
673 func (fd *FD) Dup() (int, string, error) {
674 if err := fd.incref(); err != nil {
675 return -1, "", err
676 }
677 defer fd.decref()
678 return DupCloseOnExec(fd.Sysfd)
679 }
680
681
682
683
684 func (fd *FD) WaitWrite() error {
685 return fd.pd.waitWrite(fd.isFile)
686 }
687
688
689 func (fd *FD) WriteOnce(p []byte) (int, error) {
690 if err := fd.writeLock(); err != nil {
691 return 0, err
692 }
693 defer fd.writeUnlock()
694 return ignoringEINTRIO(syscall.Write, fd.Sysfd, p)
695 }
696
697
698 func (fd *FD) RawRead(f func(uintptr) bool) error {
699 if err := fd.readLock(); err != nil {
700 return err
701 }
702 defer fd.readUnlock()
703 if err := fd.pd.prepareRead(fd.isFile); err != nil {
704 return err
705 }
706 for {
707 if f(uintptr(fd.Sysfd)) {
708 return nil
709 }
710 if err := fd.pd.waitRead(fd.isFile); err != nil {
711 return err
712 }
713 }
714 }
715
716
717 func (fd *FD) RawWrite(f func(uintptr) bool) error {
718 if err := fd.writeLock(); err != nil {
719 return err
720 }
721 defer fd.writeUnlock()
722 if err := fd.pd.prepareWrite(fd.isFile); err != nil {
723 return err
724 }
725 for {
726 if f(uintptr(fd.Sysfd)) {
727 return nil
728 }
729 if err := fd.pd.waitWrite(fd.isFile); err != nil {
730 return err
731 }
732 }
733 }
734
735
736 func ignoringEINTRIO(fn func(fd int, p []byte) (int, error), fd int, p []byte) (int, error) {
737 for {
738 n, err := fn(fd, p)
739 if err != syscall.EINTR {
740 return n, err
741 }
742 }
743 }
744
View as plain text