...

Source file src/internal/poll/fd_unix.go

Documentation: internal/poll

     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/strconv"
    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  		//
   152  		// Waiting for readability instead was proposed in
   153  		// go.dev/cl/22031 and abandoned. Blocking would change
   154  		// the behavior of existing callers, and the netpoller's
   155  		// edge-triggered notifications alone cannot detect data
   156  		// that is already buffered. See go.dev/issue/15735.
   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  // Pread wraps the pread system call.
   181  func (fd *FD) Pread(p []byte, off int64) (int, error) {
   182  	// Call incref, not readLock, because since pread specifies the
   183  	// offset it is independent from other reads.
   184  	// Similarly, using the poller doesn't make sense for pread.
   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  // ReadFrom wraps the recvfrom network call.
   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  // ReadFromInet4 wraps the recvfrom network call for IPv4.
   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  // ReadFromInet6 wraps the recvfrom network call for IPv6.
   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  // ReadMsg wraps the recvmsg network call.
   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  			// TODO(dfc) should n and oobn be set to 0
   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  // ReadMsgInet4 is ReadMsg, but specialized for syscall.SockaddrInet4.
   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  			// TODO(dfc) should n and oobn be set to 0
   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  // ReadMsgInet6 is ReadMsg, but specialized for syscall.SockaddrInet6.
   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  			// TODO(dfc) should n and oobn be set to 0
   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  // Write implements io.Writer.
   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  				// This can reportedly happen when using
   383  				// some VPN software. Issue #61060.
   384  				// If we don't check this we will panic
   385  				// with slice bounds out of range.
   386  				// Use a more informative panic.
   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  // Pwrite wraps the pwrite system call.
   409  func (fd *FD) Pwrite(p []byte, off int64) (int, error) {
   410  	// Call incref, not writeLock, because since pwrite specifies the
   411  	// offset it is independent from other writes.
   412  	// Similarly, using the poller doesn't make sense for pwrite.
   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  // WriteToInet4 wraps the sendto network call for IPv4 addresses.
   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  // WriteToInet6 wraps the sendto network call for IPv6 addresses.
   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  // WriteTo wraps the sendto network call.
   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  // WriteMsg wraps the sendmsg network call.
   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  // WriteMsgInet4 is WriteMsg specialized for syscall.SockaddrInet4.
   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  // WriteMsgInet6 is WriteMsg specialized for syscall.SockaddrInet6.
   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  // Accept wraps the accept network call.
   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  			// This means that a socket on the listen
   624  			// queue was closed before we Accept()ed it;
   625  			// it's a silly error, so try again.
   626  			continue
   627  		}
   628  		return -1, nil, errcall, err
   629  	}
   630  }
   631  
   632  // Fchmod wraps syscall.Fchmod.
   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  // Fstat wraps syscall.Fstat
   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  // dupCloexecUnsupported indicates whether F_DUPFD_CLOEXEC is supported by the kernel.
   655  var dupCloexecUnsupported atomic.Bool
   656  
   657  // DupCloseOnExec dups fd and marks it close-on-exec.
   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  			// Old kernel, or js/wasm (which returns
   667  			// ENOSYS). Fall back to the portable way from
   668  			// now on.
   669  			dupCloexecUnsupported.Store(true)
   670  		default:
   671  			return -1, "fcntl", err
   672  		}
   673  	}
   674  	return dupCloseOnExecOld(fd)
   675  }
   676  
   677  // Dup duplicates the file descriptor.
   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  // On Unix variants only, expose the IO event for the net code.
   687  
   688  // WaitWrite waits until data can be written to fd.
   689  func (fd *FD) WaitWrite() error {
   690  	return fd.pd.waitWrite(fd.isFile)
   691  }
   692  
   693  // WriteOnce is for testing only. It makes a single write call.
   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  // RawRead invokes the user-defined function f for a read operation.
   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  // RawWrite invokes the user-defined function f for a write operation.
   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  // ignoringEINTRIO is like ignoringEINTR, but just for IO calls.
   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