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

View as plain text