github.com/JimmyHuang454/JLS-go@v0.0.0-20230831150107-90d536585ba0/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) 6 7 package poll 8 9 import ( 10 "internal/syscall/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 // I/O poller. 26 pd pollDesc 27 28 // Writev cache. 29 iovecs *[]syscall.Iovec 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 // We don't actually care about the various network types. 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 // If we could not initialize the runtime poller, 66 // assume we are using blocking mode. 67 fd.isBlocking = 1 68 } 69 return err 70 } 71 72 // Destroy closes the file descriptor. This is called when there are 73 // no remaining references. 74 func (fd *FD) destroy() error { 75 // Poller may want to unregister fd in readiness notification mechanism, 76 // so this must be executed before CloseFunc. 77 fd.pd.close() 78 79 // We don't use ignoringEINTR here because POSIX does not define 80 // whether the descriptor is closed if close returns EINTR. 81 // If the descriptor is indeed closed, using a loop would race 82 // with some other goroutine opening a new descriptor. 83 // (The Linux kernel guarantees that it is closed on an EINTR error.) 84 err := CloseFunc(fd.Sysfd) 85 86 fd.Sysfd = -1 87 runtime_Semrelease(&fd.csema) 88 return err 89 } 90 91 // Close closes the FD. The underlying file descriptor is closed by the 92 // destroy method when there are no remaining references. 93 func (fd *FD) Close() error { 94 if !fd.fdmu.increfAndClose() { 95 return errClosing(fd.isFile) 96 } 97 98 // Unblock any I/O. Once it all unblocks and returns, 99 // so that it cannot be referring to fd.sysfd anymore, 100 // the final decref will close fd.sysfd. This should happen 101 // fairly quickly, since all the I/O is non-blocking, and any 102 // attempts to block in the pollDesc will return errClosing(fd.isFile). 103 fd.pd.evict() 104 105 // The call to decref will call destroy if there are no other 106 // references. 107 err := fd.decref() 108 109 // Wait until the descriptor is closed. If this was the only 110 // reference, it is already closed. Only wait if the file has 111 // not been set to blocking mode, as otherwise any current I/O 112 // may be blocking, and that would block the Close. 113 // No need for an atomic read of isBlocking, increfAndClose means 114 // we have exclusive access to fd. 115 if fd.isBlocking == 0 { 116 runtime_Semacquire(&fd.csema) 117 } 118 119 return err 120 } 121 122 // SetBlocking puts the file into blocking mode. 123 func (fd *FD) SetBlocking() error { 124 if err := fd.incref(); err != nil { 125 return err 126 } 127 defer fd.decref() 128 // Atomic store so that concurrent calls to SetBlocking 129 // do not cause a race condition. isBlocking only ever goes 130 // from 0 to 1 so there is no real race here. 131 atomic.StoreUint32(&fd.isBlocking, 1) 132 return syscall.SetNonblock(fd.Sysfd, false) 133 } 134 135 // Darwin and FreeBSD can't read or write 2GB+ files at a time, 136 // even on 64-bit systems. 137 // The same is true of socket implementations on many systems. 138 // See golang.org/issue/7812 and golang.org/issue/16266. 139 // Use 1GB instead of, say, 2GB-1, to keep subsequent reads aligned. 140 const maxRW = 1 << 30 141 142 // Read implements io.Reader. 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 // If the caller wanted a zero byte read, return immediately 150 // without trying (but after acquiring the readLock). 151 // Otherwise syscall.Read returns 0, nil which looks like 152 // io.EOF. 153 // TODO(bradfitz): make it wait for readability? (Issue 15735) 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 // Pread wraps the pread system call. 178 func (fd *FD) Pread(p []byte, off int64) (int, error) { 179 // Call incref, not readLock, because since pread specifies the 180 // offset it is independent from other reads. 181 // Similarly, using the poller doesn't make sense for pread. 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 // ReadFrom wraps the recvfrom network call. 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 // ReadFromInet4 wraps the recvfrom network call for IPv4. 234 func (fd *FD) ReadFromInet4(p []byte, from *syscall.SockaddrInet4) (int, error) { 235 if err := fd.readLock(); err != nil { 236 return 0, err 237 } 238 defer fd.readUnlock() 239 if err := fd.pd.prepareRead(fd.isFile); err != nil { 240 return 0, err 241 } 242 for { 243 n, err := unix.RecvfromInet4(fd.Sysfd, p, 0, from) 244 if err != nil { 245 if err == syscall.EINTR { 246 continue 247 } 248 n = 0 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, err 257 } 258 } 259 260 // ReadFromInet6 wraps the recvfrom network call for IPv6. 261 func (fd *FD) ReadFromInet6(p []byte, from *syscall.SockaddrInet6) (int, error) { 262 if err := fd.readLock(); err != nil { 263 return 0, err 264 } 265 defer fd.readUnlock() 266 if err := fd.pd.prepareRead(fd.isFile); err != nil { 267 return 0, err 268 } 269 for { 270 n, err := unix.RecvfromInet6(fd.Sysfd, p, 0, from) 271 if err != nil { 272 if err == syscall.EINTR { 273 continue 274 } 275 n = 0 276 if err == syscall.EAGAIN && fd.pd.pollable() { 277 if err = fd.pd.waitRead(fd.isFile); err == nil { 278 continue 279 } 280 } 281 } 282 err = fd.eofError(n, err) 283 return n, err 284 } 285 } 286 287 // ReadMsg wraps the recvmsg network call. 288 func (fd *FD) ReadMsg(p []byte, oob []byte, flags int) (int, int, int, syscall.Sockaddr, error) { 289 if err := fd.readLock(); err != nil { 290 return 0, 0, 0, nil, err 291 } 292 defer fd.readUnlock() 293 if err := fd.pd.prepareRead(fd.isFile); err != nil { 294 return 0, 0, 0, nil, err 295 } 296 for { 297 n, oobn, sysflags, sa, err := syscall.Recvmsg(fd.Sysfd, p, oob, flags) 298 if err != nil { 299 if err == syscall.EINTR { 300 continue 301 } 302 // TODO(dfc) should n and oobn be set to 0 303 if err == syscall.EAGAIN && fd.pd.pollable() { 304 if err = fd.pd.waitRead(fd.isFile); err == nil { 305 continue 306 } 307 } 308 } 309 err = fd.eofError(n, err) 310 return n, oobn, sysflags, sa, err 311 } 312 } 313 314 // ReadMsgInet4 is ReadMsg, but specialized for syscall.SockaddrInet4. 315 func (fd *FD) ReadMsgInet4(p []byte, oob []byte, flags int, sa4 *syscall.SockaddrInet4) (int, int, int, error) { 316 if err := fd.readLock(); err != nil { 317 return 0, 0, 0, err 318 } 319 defer fd.readUnlock() 320 if err := fd.pd.prepareRead(fd.isFile); err != nil { 321 return 0, 0, 0, err 322 } 323 for { 324 n, oobn, sysflags, err := unix.RecvmsgInet4(fd.Sysfd, p, oob, flags, sa4) 325 if err != nil { 326 if err == syscall.EINTR { 327 continue 328 } 329 // TODO(dfc) should n and oobn be set to 0 330 if err == syscall.EAGAIN && fd.pd.pollable() { 331 if err = fd.pd.waitRead(fd.isFile); err == nil { 332 continue 333 } 334 } 335 } 336 err = fd.eofError(n, err) 337 return n, oobn, sysflags, err 338 } 339 } 340 341 // ReadMsgInet6 is ReadMsg, but specialized for syscall.SockaddrInet6. 342 func (fd *FD) ReadMsgInet6(p []byte, oob []byte, flags int, sa6 *syscall.SockaddrInet6) (int, int, int, error) { 343 if err := fd.readLock(); err != nil { 344 return 0, 0, 0, err 345 } 346 defer fd.readUnlock() 347 if err := fd.pd.prepareRead(fd.isFile); err != nil { 348 return 0, 0, 0, err 349 } 350 for { 351 n, oobn, sysflags, err := unix.RecvmsgInet6(fd.Sysfd, p, oob, flags, sa6) 352 if err != nil { 353 if err == syscall.EINTR { 354 continue 355 } 356 // TODO(dfc) should n and oobn be set to 0 357 if err == syscall.EAGAIN && fd.pd.pollable() { 358 if err = fd.pd.waitRead(fd.isFile); err == nil { 359 continue 360 } 361 } 362 } 363 err = fd.eofError(n, err) 364 return n, oobn, sysflags, err 365 } 366 } 367 368 // Write implements io.Writer. 369 func (fd *FD) Write(p []byte) (int, error) { 370 if err := fd.writeLock(); err != nil { 371 return 0, err 372 } 373 defer fd.writeUnlock() 374 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 375 return 0, err 376 } 377 var nn int 378 for { 379 max := len(p) 380 if fd.IsStream && max-nn > maxRW { 381 max = nn + maxRW 382 } 383 n, err := ignoringEINTRIO(syscall.Write, fd.Sysfd, p[nn:max]) 384 if n > 0 { 385 nn += n 386 } 387 if nn == len(p) { 388 return nn, err 389 } 390 if err == syscall.EAGAIN && fd.pd.pollable() { 391 if err = fd.pd.waitWrite(fd.isFile); err == nil { 392 continue 393 } 394 } 395 if err != nil { 396 return nn, err 397 } 398 if n == 0 { 399 return nn, io.ErrUnexpectedEOF 400 } 401 } 402 } 403 404 // Pwrite wraps the pwrite system call. 405 func (fd *FD) Pwrite(p []byte, off int64) (int, error) { 406 // Call incref, not writeLock, because since pwrite specifies the 407 // offset it is independent from other writes. 408 // Similarly, using the poller doesn't make sense for pwrite. 409 if err := fd.incref(); err != nil { 410 return 0, err 411 } 412 defer fd.decref() 413 var nn int 414 for { 415 max := len(p) 416 if fd.IsStream && max-nn > maxRW { 417 max = nn + maxRW 418 } 419 n, err := syscall.Pwrite(fd.Sysfd, p[nn:max], off+int64(nn)) 420 if err == syscall.EINTR { 421 continue 422 } 423 if n > 0 { 424 nn += n 425 } 426 if nn == len(p) { 427 return nn, err 428 } 429 if err != nil { 430 return nn, err 431 } 432 if n == 0 { 433 return nn, io.ErrUnexpectedEOF 434 } 435 } 436 } 437 438 // WriteToInet4 wraps the sendto network call for IPv4 addresses. 439 func (fd *FD) WriteToInet4(p []byte, sa *syscall.SockaddrInet4) (int, error) { 440 if err := fd.writeLock(); err != nil { 441 return 0, err 442 } 443 defer fd.writeUnlock() 444 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 445 return 0, err 446 } 447 for { 448 err := unix.SendtoInet4(fd.Sysfd, p, 0, sa) 449 if err == syscall.EINTR { 450 continue 451 } 452 if err == syscall.EAGAIN && fd.pd.pollable() { 453 if err = fd.pd.waitWrite(fd.isFile); err == nil { 454 continue 455 } 456 } 457 if err != nil { 458 return 0, err 459 } 460 return len(p), nil 461 } 462 } 463 464 // WriteToInet6 wraps the sendto network call for IPv6 addresses. 465 func (fd *FD) WriteToInet6(p []byte, sa *syscall.SockaddrInet6) (int, error) { 466 if err := fd.writeLock(); err != nil { 467 return 0, err 468 } 469 defer fd.writeUnlock() 470 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 471 return 0, err 472 } 473 for { 474 err := unix.SendtoInet6(fd.Sysfd, p, 0, sa) 475 if err == syscall.EINTR { 476 continue 477 } 478 if err == syscall.EAGAIN && fd.pd.pollable() { 479 if err = fd.pd.waitWrite(fd.isFile); err == nil { 480 continue 481 } 482 } 483 if err != nil { 484 return 0, err 485 } 486 return len(p), nil 487 } 488 } 489 490 // WriteTo wraps the sendto network call. 491 func (fd *FD) WriteTo(p []byte, sa syscall.Sockaddr) (int, error) { 492 if err := fd.writeLock(); err != nil { 493 return 0, err 494 } 495 defer fd.writeUnlock() 496 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 497 return 0, err 498 } 499 for { 500 err := syscall.Sendto(fd.Sysfd, p, 0, sa) 501 if err == syscall.EINTR { 502 continue 503 } 504 if err == syscall.EAGAIN && fd.pd.pollable() { 505 if err = fd.pd.waitWrite(fd.isFile); err == nil { 506 continue 507 } 508 } 509 if err != nil { 510 return 0, err 511 } 512 return len(p), nil 513 } 514 } 515 516 // WriteMsg wraps the sendmsg network call. 517 func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, error) { 518 if err := fd.writeLock(); err != nil { 519 return 0, 0, err 520 } 521 defer fd.writeUnlock() 522 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 523 return 0, 0, err 524 } 525 for { 526 n, err := syscall.SendmsgN(fd.Sysfd, p, oob, sa, 0) 527 if err == syscall.EINTR { 528 continue 529 } 530 if err == syscall.EAGAIN && fd.pd.pollable() { 531 if err = fd.pd.waitWrite(fd.isFile); err == nil { 532 continue 533 } 534 } 535 if err != nil { 536 return n, 0, err 537 } 538 return n, len(oob), err 539 } 540 } 541 542 // WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4. 543 func (fd *FD) WriteMsgInet4(p []byte, oob []byte, sa *syscall.SockaddrInet4) (int, int, error) { 544 if err := fd.writeLock(); err != nil { 545 return 0, 0, err 546 } 547 defer fd.writeUnlock() 548 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 549 return 0, 0, err 550 } 551 for { 552 n, err := unix.SendmsgNInet4(fd.Sysfd, p, oob, sa, 0) 553 if err == syscall.EINTR { 554 continue 555 } 556 if err == syscall.EAGAIN && fd.pd.pollable() { 557 if err = fd.pd.waitWrite(fd.isFile); err == nil { 558 continue 559 } 560 } 561 if err != nil { 562 return n, 0, err 563 } 564 return n, len(oob), err 565 } 566 } 567 568 // WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6. 569 func (fd *FD) WriteMsgInet6(p []byte, oob []byte, sa *syscall.SockaddrInet6) (int, int, error) { 570 if err := fd.writeLock(); err != nil { 571 return 0, 0, err 572 } 573 defer fd.writeUnlock() 574 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 575 return 0, 0, err 576 } 577 for { 578 n, err := unix.SendmsgNInet6(fd.Sysfd, p, oob, sa, 0) 579 if err == syscall.EINTR { 580 continue 581 } 582 if err == syscall.EAGAIN && fd.pd.pollable() { 583 if err = fd.pd.waitWrite(fd.isFile); err == nil { 584 continue 585 } 586 } 587 if err != nil { 588 return n, 0, err 589 } 590 return n, len(oob), err 591 } 592 } 593 594 // Accept wraps the accept network call. 595 func (fd *FD) Accept() (int, syscall.Sockaddr, string, error) { 596 if err := fd.readLock(); err != nil { 597 return -1, nil, "", err 598 } 599 defer fd.readUnlock() 600 601 if err := fd.pd.prepareRead(fd.isFile); err != nil { 602 return -1, nil, "", err 603 } 604 for { 605 s, rsa, errcall, err := accept(fd.Sysfd) 606 if err == nil { 607 return s, rsa, "", err 608 } 609 switch err { 610 case syscall.EINTR: 611 continue 612 case syscall.EAGAIN: 613 if fd.pd.pollable() { 614 if err = fd.pd.waitRead(fd.isFile); err == nil { 615 continue 616 } 617 } 618 case syscall.ECONNABORTED: 619 // This means that a socket on the listen 620 // queue was closed before we Accept()ed it; 621 // it's a silly error, so try again. 622 continue 623 } 624 return -1, nil, errcall, err 625 } 626 } 627 628 // Seek wraps syscall.Seek. 629 func (fd *FD) Seek(offset int64, whence int) (int64, error) { 630 if err := fd.incref(); err != nil { 631 return 0, err 632 } 633 defer fd.decref() 634 return syscall.Seek(fd.Sysfd, offset, whence) 635 } 636 637 // ReadDirent wraps syscall.ReadDirent. 638 // We treat this like an ordinary system call rather than a call 639 // that tries to fill the buffer. 640 func (fd *FD) ReadDirent(buf []byte) (int, error) { 641 if err := fd.incref(); err != nil { 642 return 0, err 643 } 644 defer fd.decref() 645 for { 646 n, err := ignoringEINTRIO(syscall.ReadDirent, fd.Sysfd, buf) 647 if err != nil { 648 n = 0 649 if err == syscall.EAGAIN && fd.pd.pollable() { 650 if err = fd.pd.waitRead(fd.isFile); err == nil { 651 continue 652 } 653 } 654 } 655 // Do not call eofError; caller does not expect to see io.EOF. 656 return n, err 657 } 658 } 659 660 // Fchmod wraps syscall.Fchmod. 661 func (fd *FD) Fchmod(mode uint32) error { 662 if err := fd.incref(); err != nil { 663 return err 664 } 665 defer fd.decref() 666 return ignoringEINTR(func() error { 667 return syscall.Fchmod(fd.Sysfd, mode) 668 }) 669 } 670 671 // Fchdir wraps syscall.Fchdir. 672 func (fd *FD) Fchdir() error { 673 if err := fd.incref(); err != nil { 674 return err 675 } 676 defer fd.decref() 677 return syscall.Fchdir(fd.Sysfd) 678 } 679 680 // Fstat wraps syscall.Fstat 681 func (fd *FD) Fstat(s *syscall.Stat_t) error { 682 if err := fd.incref(); err != nil { 683 return err 684 } 685 defer fd.decref() 686 return ignoringEINTR(func() error { 687 return syscall.Fstat(fd.Sysfd, s) 688 }) 689 } 690 691 // tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used. 692 // If the kernel doesn't support it, this is set to 0. 693 var tryDupCloexec = int32(1) 694 695 // DupCloseOnExec dups fd and marks it close-on-exec. 696 func DupCloseOnExec(fd int) (int, string, error) { 697 if syscall.F_DUPFD_CLOEXEC != 0 && atomic.LoadInt32(&tryDupCloexec) == 1 { 698 r0, e1 := fcntl(fd, syscall.F_DUPFD_CLOEXEC, 0) 699 if e1 == nil { 700 return r0, "", nil 701 } 702 switch e1.(syscall.Errno) { 703 case syscall.EINVAL, syscall.ENOSYS: 704 // Old kernel, or js/wasm (which returns 705 // ENOSYS). Fall back to the portable way from 706 // now on. 707 atomic.StoreInt32(&tryDupCloexec, 0) 708 default: 709 return -1, "fcntl", e1 710 } 711 } 712 return dupCloseOnExecOld(fd) 713 } 714 715 // dupCloseOnExecOld is the traditional way to dup an fd and 716 // set its O_CLOEXEC bit, using two system calls. 717 func dupCloseOnExecOld(fd int) (int, string, error) { 718 syscall.ForkLock.RLock() 719 defer syscall.ForkLock.RUnlock() 720 newfd, err := syscall.Dup(fd) 721 if err != nil { 722 return -1, "dup", err 723 } 724 syscall.CloseOnExec(newfd) 725 return newfd, "", nil 726 } 727 728 // Dup duplicates the file descriptor. 729 func (fd *FD) Dup() (int, string, error) { 730 if err := fd.incref(); err != nil { 731 return -1, "", err 732 } 733 defer fd.decref() 734 return DupCloseOnExec(fd.Sysfd) 735 } 736 737 // On Unix variants only, expose the IO event for the net code. 738 739 // WaitWrite waits until data can be read from fd. 740 func (fd *FD) WaitWrite() error { 741 return fd.pd.waitWrite(fd.isFile) 742 } 743 744 // WriteOnce is for testing only. It makes a single write call. 745 func (fd *FD) WriteOnce(p []byte) (int, error) { 746 if err := fd.writeLock(); err != nil { 747 return 0, err 748 } 749 defer fd.writeUnlock() 750 return ignoringEINTRIO(syscall.Write, fd.Sysfd, p) 751 } 752 753 // RawRead invokes the user-defined function f for a read operation. 754 func (fd *FD) RawRead(f func(uintptr) bool) error { 755 if err := fd.readLock(); err != nil { 756 return err 757 } 758 defer fd.readUnlock() 759 if err := fd.pd.prepareRead(fd.isFile); err != nil { 760 return err 761 } 762 for { 763 if f(uintptr(fd.Sysfd)) { 764 return nil 765 } 766 if err := fd.pd.waitRead(fd.isFile); err != nil { 767 return err 768 } 769 } 770 } 771 772 // RawWrite invokes the user-defined function f for a write operation. 773 func (fd *FD) RawWrite(f func(uintptr) bool) error { 774 if err := fd.writeLock(); err != nil { 775 return err 776 } 777 defer fd.writeUnlock() 778 if err := fd.pd.prepareWrite(fd.isFile); err != nil { 779 return err 780 } 781 for { 782 if f(uintptr(fd.Sysfd)) { 783 return nil 784 } 785 if err := fd.pd.waitWrite(fd.isFile); err != nil { 786 return err 787 } 788 } 789 } 790 791 // ignoringEINTRIO is like ignoringEINTR, but just for IO calls. 792 func ignoringEINTRIO(fn func(fd int, p []byte) (int, error), fd int, p []byte) (int, error) { 793 for { 794 n, err := fn(fd, p) 795 if err != syscall.EINTR { 796 return n, err 797 } 798 } 799 }