github.com/bir3/gocompiler@v0.9.2202/src/internal/poll/fd_unix.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build unix || (js && wasm) || wasip1 6 7 package poll 8 9 import ( 10 "github.com/bir3/gocompiler/src/xvendor/golang.org/x/sys/unix" 11 "io" 12 "sync/atomic" 13 "syscall" 14 ) 15 16 // FD is a file descriptor. The net and os packages use this type as a 17 // field of a larger type representing a network connection or OS file. 18 type FD struct { 19 // Lock sysfd and serialize access to Read and Write methods. 20 fdmu fdMutex 21 22 // System file descriptor. Immutable until Close. 23 Sysfd int 24 25 // Platform dependent state of the file descriptor. 26 SysFile 27 28 // I/O poller. 29 pd pollDesc 30 31 // Semaphore signaled when file is closed. 32 csema uint32 33 34 // Non-zero if this file has been set to blocking mode. 35 isBlocking uint32 36 37 // Whether this is a streaming descriptor, as opposed to a 38 // packet-based descriptor like a UDP socket. Immutable. 39 IsStream bool 40 41 // Whether a zero byte read indicates EOF. This is false for a 42 // message based socket connection. 43 ZeroReadIsEOF bool 44 45 // Whether this is a file rather than a network socket. 46 isFile bool 47 } 48 49 // Init initializes the FD. The Sysfd field should already be set. 50 // This can be called multiple times on a single FD. 51 // The net argument is a network name from the net package (e.g., "tcp"), 52 // or "file". 53 // Set pollable to true if fd should be managed by runtime netpoll. 54 func (fd *FD) Init(net string, pollable bool) error { 55 fd.SysFile.init() 56 57 // We don't actually care about the various network types. 58 if net == "file" { 59 fd.isFile = true 60 } 61 if !pollable { 62 fd.isBlocking = 1 63 return nil 64 } 65 err := fd.pd.init(fd) 66 if err != nil { 67 // If we could not initialize the runtime poller, 68 // assume we are using blocking mode. 69 fd.isBlocking = 1 70 } 71 return err 72 } 73 74 // Destroy closes the file descriptor. This is called when there are 75 // no remaining references. 76 func (fd *FD) destroy() error { 77 // Poller may want to unregister fd in readiness notification mechanism, 78 // so this must be executed before CloseFunc. 79 fd.pd.close() 80 81 err := fd.SysFile.destroy(fd.Sysfd) 82 83 fd.Sysfd = -1 84 runtime_Semrelease(&fd.csema) 85 return err 86 } 87 88 // Close closes the FD. The underlying file descriptor is closed by the 89 // destroy method when there are no remaining references. 90 func (fd *FD) Close() error { 91 if !fd.fdmu.increfAndClose() { 92 return errClosing(fd.isFile) 93 } 94 95 // Unblock any I/O. Once it all unblocks and returns, 96 // so that it cannot be referring to fd.sysfd anymore, 97 // the final decref will close fd.sysfd. This should happen 98 // fairly quickly, since all the I/O is non-blocking, and any 99 // attempts to block in the pollDesc will return errClosing(fd.isFile). 100 fd.pd.evict() 101 102 // The call to decref will call destroy if there are no other 103 // references. 104 err := fd.decref() 105 106 // Wait until the descriptor is closed. If this was the only 107 // reference, it is already closed. Only wait if the file has 108 // not been set to blocking mode, as otherwise any current I/O 109 // may be blocking, and that would block the Close. 110 // No need for an atomic read of isBlocking, increfAndClose means 111 // we have exclusive access to fd. 112 if fd.isBlocking == 0 { 113 runtime_Semacquire(&fd.csema) 114 } 115 116 return err 117 } 118 119 // SetBlocking puts the file into blocking mode. 120 func (fd *FD) SetBlocking() error { 121 if err := fd.incref(); err != nil { 122 return err 123 } 124 defer fd.decref() 125 // Atomic store so that concurrent calls to SetBlocking 126 // do not cause a race condition. isBlocking only ever goes 127 // from 0 to 1 so there is no real race here. 128 atomic.StoreUint32(&fd.isBlocking, 1) 129 return syscall.SetNonblock(fd.Sysfd, false) 130 } 131 132 // Darwin and FreeBSD can't read or write 2GB+ files at a time, 133 // even on 64-bit systems. 134 // The same is true of socket implementations on many systems. 135 // See golang.org/issue/7812 and golang.org/issue/16266. 136 // Use 1GB instead of, say, 2GB-1, to keep subsequent reads aligned. 137 const maxRW = 1 << 30 138 139 // Read implements io.Reader. 140 func (fd *FD) Read(p []byte) (int, error) { 141 if err := fd.readLock(); err != nil { 142 return 0, err 143 } 144 defer fd.readUnlock() 145 if len(p) == 0 { 146 // If the caller wanted a zero byte read, return immediately 147 // without trying (but after acquiring the readLock). 148 // Otherwise syscall.Read returns 0, nil which looks like 149 // io.EOF. 150 // TODO(bradfitz): make it wait for readability? (Issue 15735) 151 return 0, nil 152 } 153 if err := fd.pd.prepareRead(fd.isFile); err != nil { 154 return 0, err 155 } 156 if fd.IsStream && len(p) > maxRW { 157 p = p[:maxRW] 158 } 159 for { 160 n, err := ignoringEINTRIO(syscall.Read, fd.Sysfd, p) 161 if err != nil { 162 n = 0 163 if err == syscall.EAGAIN && fd.pd.pollable() { 164 if err = fd.pd.waitRead(fd.isFile); err == nil { 165 continue 166 } 167 } 168 } 169 err = fd.eofError(n, err) 170 return n, err 171 } 172 } 173 174 // Pread wraps the pread system call. 175 func (fd *FD) Pread(p []byte, off int64) (int, error) { 176 // Call incref, not readLock, because since pread specifies the 177 // offset it is independent from other reads. 178 // Similarly, using the poller doesn't make sense for pread. 179 if err := fd.incref(); err != nil { 180 return 0, err 181 } 182 if fd.IsStream && len(p) > maxRW { 183 p = p[:maxRW] 184 } 185 var ( 186 n int 187 err error 188 ) 189 for { 190 n, err = syscall.Pread(fd.Sysfd, p, off) 191 if err != syscall.EINTR { 192 break 193 } 194 } 195 if err != nil { 196 n = 0 197 } 198 fd.decref() 199 err = fd.eofError(n, err) 200 return n, err 201 } 202 203 // ReadFrom wraps the recvfrom network call. 204 func (fd *FD) ReadFrom(p []byte) (int, syscall.Sockaddr, error) { 205 if err := fd.readLock(); err != nil { 206 return 0, nil, err 207 } 208 defer fd.readUnlock() 209 if err := fd.pd.prepareRead(fd.isFile); err != nil { 210 return 0, nil, err 211 } 212 for { 213 n, sa, err := syscall.Recvfrom(fd.Sysfd, p, 0) 214 if err != nil { 215 if err == syscall.EINTR { 216 continue 217 } 218 n = 0 219 if err == syscall.EAGAIN && fd.pd.pollable() { 220 if err = fd.pd.waitRead(fd.isFile); err == nil { 221 continue 222 } 223 } 224 } 225 err = fd.eofError(n, err) 226 return n, sa, err 227 } 228 } 229 230 // ReadFromInet4 wraps the recvfrom network call for IPv4. 231 func (fd *FD) ReadFromInet4(p []byte, from *syscall.SockaddrInet4) (int, error) { 232 if err := fd.readLock(); err != nil { 233 return 0, err 234 } 235 defer fd.readUnlock() 236 if err := fd.pd.prepareRead(fd.isFile); err != nil { 237 return 0, err 238 } 239 for { 240 n, err := unix.RecvfromInet4(fd.Sysfd, p, 0, from) 241 if err != nil { 242 if err == syscall.EINTR { 243 continue 244 } 245 n = 0 246 if err == syscall.EAGAIN && fd.pd.pollable() { 247 if err = fd.pd.waitRead(fd.isFile); err == nil { 248 continue 249 } 250 } 251 } 252 err = fd.eofError(n, err) 253 return n, err 254 } 255 } 256 257 // ReadFromInet6 wraps the recvfrom network call for IPv6. 258 func (fd *FD) ReadFromInet6(p []byte, from *syscall.SockaddrInet6) (int, error) { 259 if err := fd.readLock(); err != nil { 260 return 0, err 261 } 262 defer fd.readUnlock() 263 if err := fd.pd.prepareRead(fd.isFile); err != nil { 264 return 0, err 265 } 266 for { 267 n, err := unix.RecvfromInet6(fd.Sysfd, p, 0, from) 268 if err != nil { 269 if err == syscall.EINTR { 270 continue 271 } 272 n = 0 273 if err == syscall.EAGAIN && fd.pd.pollable() { 274 if err = fd.pd.waitRead(fd.isFile); err == nil { 275 continue 276 } 277 } 278 } 279 err = fd.eofError(n, err) 280 return n, err 281 } 282 } 283 284 // ReadMsg wraps the recvmsg network call. 285 func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) { 286 if err := fd.readLock(); err != nil { 287 return 0, 0, 0, nil, err 288 } 289 defer fd.readUnlock() 290 if err := fd.pd.prepareRead(fd.isFile); err != nil { 291 return 0, 0, 0, nil, err 292 } 293 for { 294 n, oobn, sysflags, sa, err := syscall.Recvmsg(fd.Sysfd, p, oob, flags) 295 if err != nil { 296 if err == syscall.EINTR { 297 continue 298 } 299 // TODO(dfc) should n and oobn be set to 0 300 if err == syscall.EAGAIN && fd.pd.pollable() { 301 if err = fd.pd.waitRead(fd.isFile); err == nil { 302 continue 303 } 304 } 305 } 306 err = fd.eofError(n, err) 307 return n, oobn, sysflags, sa, err 308 } 309 } 310 311 // ReadMsgInet4 is ReadMsg, but specialized for syscall.SockaddrInet4. 312 func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.SockaddrInet4) (int, int, int, error) { 313 if err := fd.readLock(); err != nil { 314 return 0, 0, 0, err 315 } 316 defer fd.readUnlock() 317 if err := fd.pd.prepareRead(fd.isFile); err != nil { 318 return 0, 0, 0, err 319 } 320 for { 321 n, oobn, sysflags, err := unix.RecvmsgInet4(fd.Sysfd, p, oob, flags, sa4) 322 if err != nil { 323 if err == syscall.EINTR { 324 continue 325 } 326 // TODO(dfc) should n and oobn be set to 0 327 if err == syscall.EAGAIN && fd.pd.pollable() { 328 if err = fd.pd.waitRead(fd.isFile); err == nil { 329 continue 330 } 331 } 332 } 333 err = fd.eofError(n, err) 334 return n, oobn, sysflags, err 335 } 336 } 337 338 // ReadMsgInet6 is ReadMsg, but specialized for syscall.SockaddrInet6. 339 func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.SockaddrInet6) (int, int, int, error) { 340 if err := fd.readLock(); err != nil { 341 return 0, 0, 0, err 342 } 343 defer fd.readUnlock() 344 if err := fd.pd.prepareRead(fd.isFile); err != nil { 345 return 0, 0, 0, err 346 } 347 for { 348 n, oobn, sysflags, err := unix.RecvmsgInet6(fd.Sysfd, p, oob, flags, sa6) 349 if err != nil { 350 if err == syscall.EINTR { 351 continue 352 } 353 // TODO(dfc) should n and oobn be set to 0 354 if err == syscall.EAGAIN && fd.pd.pollable() { 355 if err = fd.pd.waitRead(fd.isFile); err == nil { 356 continue 357 } 358 } 359 } 360 err = fd.eofError(n, err) 361 return n, oobn, sysflags, err 362 } 363 } 364 365 // Write implements io.Writer. 366 func (fd *FD) Write(p []byte) (int, error) { 367 if err := fd.writeLock(); err != nil { 368 return 0, err 369 } 370 defer fd.writeUnlock() 371 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 372 return 0, err 373 } 374 var nn int 375 for { 376 max := len(p) 377 if fd.IsStream && max-nn > maxRW { 378 max = nn + maxRW 379 } 380 n, err := ignoringEINTRIO(syscall.Write, fd.Sysfd, p[nn:max]) 381 if n > 0 { 382 nn += n 383 } 384 if nn == len(p) { 385 return nn, err 386 } 387 if err == syscall.EAGAIN && fd.pd.pollable() { 388 if err = fd.pd.waitWrite(fd.isFile); err == nil { 389 continue 390 } 391 } 392 if err != nil { 393 return nn, err 394 } 395 if n == 0 { 396 return nn, io.ErrUnexpectedEOF 397 } 398 } 399 } 400 401 // Pwrite wraps the pwrite system call. 402 func (fd *FD) Pwrite(p []byte, off int64) (int, error) { 403 // Call incref, not writeLock, because since pwrite specifies the 404 // offset it is independent from other writes. 405 // Similarly, using the poller doesn't make sense for pwrite. 406 if err := fd.incref(); err != nil { 407 return 0, err 408 } 409 defer fd.decref() 410 var nn int 411 for { 412 max := len(p) 413 if fd.IsStream && max-nn > maxRW { 414 max = nn + maxRW 415 } 416 n, err := syscall.Pwrite(fd.Sysfd, p[nn:max], off+int64(nn)) 417 if err == syscall.EINTR { 418 continue 419 } 420 if n > 0 { 421 nn += n 422 } 423 if nn == len(p) { 424 return nn, err 425 } 426 if err != nil { 427 return nn, err 428 } 429 if n == 0 { 430 return nn, io.ErrUnexpectedEOF 431 } 432 } 433 } 434 435 // WriteToInet4 wraps the sendto network call for IPv4 addresses. 436 func (fd *FD) WriteToInet4(p []byte, sa *syscall.SockaddrInet4) (int, error) { 437 if err := fd.writeLock(); err != nil { 438 return 0, err 439 } 440 defer fd.writeUnlock() 441 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 442 return 0, err 443 } 444 for { 445 err := unix.SendtoInet4(fd.Sysfd, p, 0, sa) 446 if err == syscall.EINTR { 447 continue 448 } 449 if err == syscall.EAGAIN && fd.pd.pollable() { 450 if err = fd.pd.waitWrite(fd.isFile); err == nil { 451 continue 452 } 453 } 454 if err != nil { 455 return 0, err 456 } 457 return len(p), nil 458 } 459 } 460 461 // WriteToInet6 wraps the sendto network call for IPv6 addresses. 462 func (fd *FD) WriteToInet6(p []byte, sa *syscall.SockaddrInet6) (int, error) { 463 if err := fd.writeLock(); err != nil { 464 return 0, err 465 } 466 defer fd.writeUnlock() 467 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 468 return 0, err 469 } 470 for { 471 err := unix.SendtoInet6(fd.Sysfd, p, 0, sa) 472 if err == syscall.EINTR { 473 continue 474 } 475 if err == syscall.EAGAIN && fd.pd.pollable() { 476 if err = fd.pd.waitWrite(fd.isFile); err == nil { 477 continue 478 } 479 } 480 if err != nil { 481 return 0, err 482 } 483 return len(p), nil 484 } 485 } 486 487 // WriteTo wraps the sendto network call. 488 func (fd *FD) WriteTo(p []byte, sa syscall.Sockaddr) (int, error) { 489 if err := fd.writeLock(); err != nil { 490 return 0, err 491 } 492 defer fd.writeUnlock() 493 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 494 return 0, err 495 } 496 for { 497 err := syscall.Sendto(fd.Sysfd, p, 0, sa) 498 if err == syscall.EINTR { 499 continue 500 } 501 if err == syscall.EAGAIN && fd.pd.pollable() { 502 if err = fd.pd.waitWrite(fd.isFile); err == nil { 503 continue 504 } 505 } 506 if err != nil { 507 return 0, err 508 } 509 return len(p), nil 510 } 511 } 512 513 // WriteMsg wraps the sendmsg network call. 514 func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, error) { 515 if err := fd.writeLock(); err != nil { 516 return 0, 0, err 517 } 518 defer fd.writeUnlock() 519 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 520 return 0, 0, err 521 } 522 for { 523 n, err := syscall.SendmsgN(fd.Sysfd, p, oob, sa, 0) 524 if err == syscall.EINTR { 525 continue 526 } 527 if err == syscall.EAGAIN && fd.pd.pollable() { 528 if err = fd.pd.waitWrite(fd.isFile); err == nil { 529 continue 530 } 531 } 532 if err != nil { 533 return n, 0, err 534 } 535 return n, len(oob), err 536 } 537 } 538 539 // WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4. 540 func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (int, int, error) { 541 if err := fd.writeLock(); err != nil { 542 return 0, 0, err 543 } 544 defer fd.writeUnlock() 545 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 546 return 0, 0, err 547 } 548 for { 549 n, err := unix.SendmsgNInet4(fd.Sysfd, p, oob, sa, 0) 550 if err == syscall.EINTR { 551 continue 552 } 553 if err == syscall.EAGAIN && fd.pd.pollable() { 554 if err = fd.pd.waitWrite(fd.isFile); err == nil { 555 continue 556 } 557 } 558 if err != nil { 559 return n, 0, err 560 } 561 return n, len(oob), err 562 } 563 } 564 565 // WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6. 566 func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (int, int, error) { 567 if err := fd.writeLock(); err != nil { 568 return 0, 0, err 569 } 570 defer fd.writeUnlock() 571 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 572 return 0, 0, err 573 } 574 for { 575 n, err := unix.SendmsgNInet6(fd.Sysfd, p, oob, sa, 0) 576 if err == syscall.EINTR { 577 continue 578 } 579 if err == syscall.EAGAIN && fd.pd.pollable() { 580 if err = fd.pd.waitWrite(fd.isFile); err == nil { 581 continue 582 } 583 } 584 if err != nil { 585 return n, 0, err 586 } 587 return n, len(oob), err 588 } 589 } 590 591 // Accept wraps the accept network call. 592 func (fd *FD) Accept() (int, syscall.Sockaddr, string, error) { 593 if err := fd.readLock(); err != nil { 594 return -1, nil, "", err 595 } 596 defer fd.readUnlock() 597 598 if err := fd.pd.prepareRead(fd.isFile); err != nil { 599 return -1, nil, "", err 600 } 601 for { 602 s, rsa, errcall, err := accept(fd.Sysfd) 603 if err == nil { 604 return s, rsa, "", err 605 } 606 switch err { 607 case syscall.EINTR: 608 continue 609 case syscall.EAGAIN: 610 if fd.pd.pollable() { 611 if err = fd.pd.waitRead(fd.isFile); err == nil { 612 continue 613 } 614 } 615 case syscall.ECONNABORTED: 616 // This means that a socket on the listen 617 // queue was closed before we Accept()ed it; 618 // it's a silly error, so try again. 619 continue 620 } 621 return -1, nil, errcall, err 622 } 623 } 624 625 // Fchmod wraps syscall.Fchmod. 626 func (fd *FD) Fchmod(mode uint32) error { 627 if err := fd.incref(); err != nil { 628 return err 629 } 630 defer fd.decref() 631 return ignoringEINTR(func() error { 632 return syscall.Fchmod(fd.Sysfd, mode) 633 }) 634 } 635 636 // Fstat wraps syscall.Fstat 637 func (fd *FD) Fstat(s *syscall.Stat_t) error { 638 if err := fd.incref(); err != nil { 639 return err 640 } 641 defer fd.decref() 642 return ignoringEINTR(func() error { 643 return syscall.Fstat(fd.Sysfd, s) 644 }) 645 } 646 647 // dupCloexecUnsupported indicates whether F_DUPFD_CLOEXEC is supported by the kernel. 648 var dupCloexecUnsupported atomic.Bool 649 650 // DupCloseOnExec dups fd and marks it close-on-exec. 651 func DupCloseOnExec(fd int) (int, string, error) { 652 if syscall.F_DUPFD_CLOEXEC != 0 && !dupCloexecUnsupported.Load() { 653 r0, err := unix.Fcntl(fd, syscall.F_DUPFD_CLOEXEC, 0) 654 if err == nil { 655 return r0, "", nil 656 } 657 switch err { 658 case syscall.EINVAL, syscall.ENOSYS: 659 // Old kernel, or js/wasm (which returns 660 // ENOSYS). Fall back to the portable way from 661 // now on. 662 dupCloexecUnsupported.Store(true) 663 default: 664 return -1, "fcntl", err 665 } 666 } 667 return dupCloseOnExecOld(fd) 668 } 669 670 // Dup duplicates the file descriptor. 671 func (fd *FD) Dup() (int, string, error) { 672 if err := fd.incref(); err != nil { 673 return -1, "", err 674 } 675 defer fd.decref() 676 return DupCloseOnExec(fd.Sysfd) 677 } 678 679 // On Unix variants only, expose the IO event for the net code. 680 681 // WaitWrite waits until data can be read from fd. 682 func (fd *FD) WaitWrite() error { 683 return fd.pd.waitWrite(fd.isFile) 684 } 685 686 // WriteOnce is for testing only. It makes a single write call. 687 func (fd *FD) WriteOnce(p []byte) (int, error) { 688 if err := fd.writeLock(); err != nil { 689 return 0, err 690 } 691 defer fd.writeUnlock() 692 return ignoringEINTRIO(syscall.Write, fd.Sysfd, p) 693 } 694 695 // RawRead invokes the user-defined function f for a read operation. 696 func (fd *FD) RawRead(f func(uintptr) bool) error { 697 if err := fd.readLock(); err != nil { 698 return err 699 } 700 defer fd.readUnlock() 701 if err := fd.pd.prepareRead(fd.isFile); err != nil { 702 return err 703 } 704 for { 705 if f(uintptr(fd.Sysfd)) { 706 return nil 707 } 708 if err := fd.pd.waitRead(fd.isFile); err != nil { 709 return err 710 } 711 } 712 } 713 714 // RawWrite invokes the user-defined function f for a write operation. 715 func (fd *FD) RawWrite(f func(uintptr) bool) error { 716 if err := fd.writeLock(); err != nil { 717 return err 718 } 719 defer fd.writeUnlock() 720 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 721 return err 722 } 723 for { 724 if f(uintptr(fd.Sysfd)) { 725 return nil 726 } 727 if err := fd.pd.waitWrite(fd.isFile); err != nil { 728 return err 729 } 730 } 731 } 732 733 // ignoringEINTRIO is like ignoringEINTR, but just for IO calls. 734 func ignoringEINTRIO(fn func(fd int, p []byte) (int, error), fd int, p []byte) (int, error) { 735 for { 736 n, err := fn(fd, p) 737 if err != syscall.EINTR { 738 return n, err 739 } 740 } 741 }