Source file src/internal/poll/fd_unix.go

     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  	"internal/itoa"
    11  	"internal/syscall/unix"
    12  	"io"
    13  	"sync/atomic"
    14  	"syscall"
    15  )
    16  
    17  // FD is a file descriptor. The net and os packages use this type as a
    18  // field of a larger type representing a network connection or OS file.
    19  type FD struct {
    20  	// Lock sysfd and serialize access to Read and Write methods.
    21  	fdmu fdMutex
    22  
    23  	// System file descriptor. Immutable until Close.
    24  	Sysfd int
    25  
    26  	// Platform dependent state of the file descriptor.
    27  	SysFile
    28  
    29  	// I/O poller.
    30  	pd pollDesc
    31  
    32  	// Semaphore signaled when file is closed.
    33  	csema uint32
    34  
    35  	// Non-zero if this file has been set to blocking mode.
    36  	isBlocking uint32
    37  
    38  	// Whether this is a streaming descriptor, as opposed to a
    39  	// packet-based descriptor like a UDP socket. Immutable.
    40  	IsStream bool
    41  
    42  	// Whether a zero byte read indicates EOF. This is false for a
    43  	// message based socket connection.
    44  	ZeroReadIsEOF bool
    45  
    46  	// Whether this is a file rather than a network socket.
    47  	isFile bool
    48  }
    49  
    50  // Init initializes the FD. The Sysfd field should already be set.
    51  // This can be called multiple times on a single FD.
    52  // The net argument is a network name from the net package (e.g., "tcp"),
    53  // or "file".
    54  // Set pollable to true if fd should be managed by runtime netpoll.
    55  func (fd *FD) Init(net string, pollable bool) error {
    56  	fd.SysFile.init()
    57  
    58  	// We don't actually care about the various network types.
    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  		// If we could not initialize the runtime poller,
    69  		// assume we are using blocking mode.
    70  		fd.isBlocking = 1
    71  	}
    72  	return err
    73  }
    74  
    75  // Destroy closes the file descriptor. This is called when there are
    76  // no remaining references.
    77  func (fd *FD) destroy() error {
    78  	// Poller may want to unregister fd in readiness notification mechanism,
    79  	// so this must be executed before CloseFunc.
    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  // Close closes the FD. The underlying file descriptor is closed by the
    90  // destroy method when there are no remaining references.
    91  func (fd *FD) Close() error {
    92  	if !fd.fdmu.increfAndClose() {
    93  		return errClosing(fd.isFile)
    94  	}
    95  
    96  	// Unblock any I/O.  Once it all unblocks and returns,
    97  	// so that it cannot be referring to fd.sysfd anymore,
    98  	// the final decref will close fd.sysfd. This should happen
    99  	// fairly quickly, since all the I/O is non-blocking, and any
   100  	// attempts to block in the pollDesc will return errClosing(fd.isFile).
   101  	fd.pd.evict()
   102  
   103  	// The call to decref will call destroy if there are no other
   104  	// references.
   105  	err := fd.decref()
   106  
   107  	// Wait until the descriptor is closed. If this was the only
   108  	// reference, it is already closed. Only wait if the file has
   109  	// not been set to blocking mode, as otherwise any current I/O
   110  	// may be blocking, and that would block the Close.
   111  	// No need for an atomic read of isBlocking, increfAndClose means
   112  	// we have exclusive access to fd.
   113  	if fd.isBlocking == 0 {
   114  		runtime_Semacquire(&fd.csema)
   115  	}
   116  
   117  	return err
   118  }
   119  
   120  // SetBlocking puts the file into blocking mode.
   121  func (fd *FD) SetBlocking() error {
   122  	if err := fd.incref(); err != nil {
   123  		return err
   124  	}
   125  	defer fd.decref()
   126  	// Atomic store so that concurrent calls to SetBlocking
   127  	// do not cause a race condition. isBlocking only ever goes
   128  	// from 0 to 1 so there is no real race here.
   129  	atomic.StoreUint32(&fd.isBlocking, 1)
   130  	return syscall.SetNonblock(fd.Sysfd, false)
   131  }
   132  
   133  // Darwin and FreeBSD can't read or write 2GB+ files at a time,
   134  // even on 64-bit systems.
   135  // The same is true of socket implementations on many systems.
   136  // See golang.org/issue/7812 and golang.org/issue/16266.
   137  // Use 1GB instead of, say, 2GB-1, to keep subsequent reads aligned.
   138  const maxRW = 1 << 30
   139  
   140  // Read implements io.Reader.
   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  		// If the caller wanted a zero byte read, return immediately
   148  		// without trying (but after acquiring the readLock).
   149  		// Otherwise syscall.Read returns 0, nil which looks like
   150  		// io.EOF.
   151  		// TODO(bradfitz): make it wait for readability? (Issue 15735)
   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  // Pread wraps the pread system call.
   176  func (fd *FD) Pread(p []byte, off int64) (int, error) {
   177  	// Call incref, not readLock, because since pread specifies the
   178  	// offset it is independent from other reads.
   179  	// Similarly, using the poller doesn't make sense for pread.
   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  // ReadFrom wraps the recvfrom network call.
   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  // ReadFromInet4 wraps the recvfrom network call for IPv4.
   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  // ReadFromInet6 wraps the recvfrom network call for IPv6.
   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  // ReadMsg wraps the recvmsg network call.
   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  			// TODO(dfc) should n and oobn be set to 0
   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  // ReadMsgInet4 is ReadMsg, but specialized for syscall.SockaddrInet4.
   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  			// TODO(dfc) should n and oobn be set to 0
   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  // ReadMsgInet6 is ReadMsg, but specialized for syscall.SockaddrInet6.
   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  			// TODO(dfc) should n and oobn be set to 0
   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  // Write implements io.Writer.
   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  				// This can reportedly happen when using
   378  				// some VPN software. Issue #61060.
   379  				// If we don't check this we will panic
   380  				// with slice bounds out of range.
   381  				// Use a more informative panic.
   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  // Pwrite wraps the pwrite system call.
   404  func (fd *FD) Pwrite(p []byte, off int64) (int, error) {
   405  	// Call incref, not writeLock, because since pwrite specifies the
   406  	// offset it is independent from other writes.
   407  	// Similarly, using the poller doesn't make sense for pwrite.
   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  // WriteToInet4 wraps the sendto network call for IPv4 addresses.
   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  // WriteToInet6 wraps the sendto network call for IPv6 addresses.
   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  // WriteTo wraps the sendto network call.
   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  // WriteMsg wraps the sendmsg network call.
   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  // WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4.
   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  // WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6.
   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  // Accept wraps the accept network call.
   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  			// This means that a socket on the listen
   619  			// queue was closed before we Accept()ed it;
   620  			// it's a silly error, so try again.
   621  			continue
   622  		}
   623  		return -1, nil, errcall, err
   624  	}
   625  }
   626  
   627  // Fchmod wraps syscall.Fchmod.
   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  // Fstat wraps syscall.Fstat
   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  // dupCloexecUnsupported indicates whether F_DUPFD_CLOEXEC is supported by the kernel.
   650  var dupCloexecUnsupported atomic.Bool
   651  
   652  // DupCloseOnExec dups fd and marks it close-on-exec.
   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  			// Old kernel, or js/wasm (which returns
   662  			// ENOSYS). Fall back to the portable way from
   663  			// now on.
   664  			dupCloexecUnsupported.Store(true)
   665  		default:
   666  			return -1, "fcntl", err
   667  		}
   668  	}
   669  	return dupCloseOnExecOld(fd)
   670  }
   671  
   672  // Dup duplicates the file descriptor.
   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  // On Unix variants only, expose the IO event for the net code.
   682  
   683  // WaitWrite waits until data can be written to fd.
   684  func (fd *FD) WaitWrite() error {
   685  	return fd.pd.waitWrite(fd.isFile)
   686  }
   687  
   688  // WriteOnce is for testing only. It makes a single write call.
   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  // RawRead invokes the user-defined function f for a read operation.
   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  // RawWrite invokes the user-defined function f for a write operation.
   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  // ignoringEINTRIO is like ignoringEINTR, but just for IO calls.
   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