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