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

View as plain text