github.com/hlts2/go@v0.0.0-20170904000733-812b34efaed8/src/internal/poll/fd_unix.go (about)

     1  // Copyright 2017 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
     6  
     7  package poll
     8  
     9  import (
    10  	"io"
    11  	"syscall"
    12  )
    13  
    14  // FD is a file descriptor. The net and os packages use this type as a
    15  // field of a larger type representing a network connection or OS file.
    16  type FD struct {
    17  	// Lock sysfd and serialize access to Read and Write methods.
    18  	fdmu fdMutex
    19  
    20  	// System file descriptor. Immutable until Close.
    21  	Sysfd int
    22  
    23  	// I/O poller.
    24  	pd pollDesc
    25  
    26  	// Writev cache.
    27  	iovecs *[]syscall.Iovec
    28  
    29  	// Whether this is a streaming descriptor, as opposed to a
    30  	// packet-based descriptor like a UDP socket. Immutable.
    31  	IsStream bool
    32  
    33  	// Whether a zero byte read indicates EOF. This is false for a
    34  	// message based socket connection.
    35  	ZeroReadIsEOF bool
    36  
    37  	// Whether this is a file rather than a network socket.
    38  	isFile bool
    39  }
    40  
    41  // Init initializes the FD. The Sysfd field should already be set.
    42  // This can be called multiple times on a single FD.
    43  // The net argument is a network name from the net package (e.g., "tcp"),
    44  // or "file".
    45  func (fd *FD) Init(net string, pollable bool) error {
    46  	// We don't actually care about the various network types.
    47  	if net == "file" {
    48  		fd.isFile = true
    49  	}
    50  	if !pollable {
    51  		return nil
    52  	}
    53  	return fd.pd.init(fd)
    54  }
    55  
    56  // Destroy closes the file descriptor. This is called when there are
    57  // no remaining references.
    58  func (fd *FD) destroy() error {
    59  	// Poller may want to unregister fd in readiness notification mechanism,
    60  	// so this must be executed before CloseFunc.
    61  	fd.pd.close()
    62  	err := CloseFunc(fd.Sysfd)
    63  	fd.Sysfd = -1
    64  	return err
    65  }
    66  
    67  // Close closes the FD. The underlying file descriptor is closed by the
    68  // destroy method when there are no remaining references.
    69  func (fd *FD) Close() error {
    70  	if !fd.fdmu.increfAndClose() {
    71  		return errClosing(fd.isFile)
    72  	}
    73  	// Unblock any I/O.  Once it all unblocks and returns,
    74  	// so that it cannot be referring to fd.sysfd anymore,
    75  	// the final decref will close fd.sysfd. This should happen
    76  	// fairly quickly, since all the I/O is non-blocking, and any
    77  	// attempts to block in the pollDesc will return errClosing(fd.isFile).
    78  	fd.pd.evict()
    79  	// The call to decref will call destroy if there are no other
    80  	// references.
    81  	return fd.decref()
    82  }
    83  
    84  // Shutdown wraps the shutdown network call.
    85  func (fd *FD) Shutdown(how int) error {
    86  	if err := fd.incref(); err != nil {
    87  		return err
    88  	}
    89  	defer fd.decref()
    90  	return syscall.Shutdown(fd.Sysfd, how)
    91  }
    92  
    93  // Darwin and FreeBSD can't read or write 2GB+ files at a time,
    94  // even on 64-bit systems.
    95  // The same is true of socket implementations on many systems.
    96  // See golang.org/issue/7812 and golang.org/issue/16266.
    97  // Use 1GB instead of, say, 2GB-1, to keep subsequent reads aligned.
    98  const maxRW = 1 << 30
    99  
   100  // Read implements io.Reader.
   101  func (fd *FD) Read(p []byte) (int, error) {
   102  	if err := fd.readLock(); err != nil {
   103  		return 0, err
   104  	}
   105  	defer fd.readUnlock()
   106  	if len(p) == 0 {
   107  		// If the caller wanted a zero byte read, return immediately
   108  		// without trying (but after acquiring the readLock).
   109  		// Otherwise syscall.Read returns 0, nil which looks like
   110  		// io.EOF.
   111  		// TODO(bradfitz): make it wait for readability? (Issue 15735)
   112  		return 0, nil
   113  	}
   114  	if err := fd.pd.prepareRead(fd.isFile); err != nil {
   115  		return 0, err
   116  	}
   117  	if fd.IsStream && len(p) > maxRW {
   118  		p = p[:maxRW]
   119  	}
   120  	for {
   121  		n, err := syscall.Read(fd.Sysfd, p)
   122  		if err != nil {
   123  			n = 0
   124  			if err == syscall.EAGAIN && fd.pd.pollable() {
   125  				if err = fd.pd.waitRead(fd.isFile); err == nil {
   126  					continue
   127  				}
   128  			}
   129  		}
   130  		err = fd.eofError(n, err)
   131  		return n, err
   132  	}
   133  }
   134  
   135  // Pread wraps the pread system call.
   136  func (fd *FD) Pread(p []byte, off int64) (int, error) {
   137  	// Call incref, not readLock, because since pread specifies the
   138  	// offset it is independent from other reads.
   139  	// Similarly, using the poller doesn't make sense for pread.
   140  	if err := fd.incref(); err != nil {
   141  		return 0, err
   142  	}
   143  	if fd.IsStream && len(p) > maxRW {
   144  		p = p[:maxRW]
   145  	}
   146  	n, err := syscall.Pread(fd.Sysfd, p, off)
   147  	if err != nil {
   148  		n = 0
   149  	}
   150  	fd.decref()
   151  	err = fd.eofError(n, err)
   152  	return n, err
   153  }
   154  
   155  // ReadFrom wraps the recvfrom network call.
   156  func (fd *FD) ReadFrom(p []byte) (int, syscall.Sockaddr, error) {
   157  	if err := fd.readLock(); err != nil {
   158  		return 0, nil, err
   159  	}
   160  	defer fd.readUnlock()
   161  	if err := fd.pd.prepareRead(fd.isFile); err != nil {
   162  		return 0, nil, err
   163  	}
   164  	for {
   165  		n, sa, err := syscall.Recvfrom(fd.Sysfd, p, 0)
   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, sa, err
   176  	}
   177  }
   178  
   179  // ReadMsg wraps the recvmsg network call.
   180  func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, error) {
   181  	if err := fd.readLock(); err != nil {
   182  		return 0, 0, 0, nil, err
   183  	}
   184  	defer fd.readUnlock()
   185  	if err := fd.pd.prepareRead(fd.isFile); err != nil {
   186  		return 0, 0, 0, nil, err
   187  	}
   188  	for {
   189  		n, oobn, flags, sa, err := syscall.Recvmsg(fd.Sysfd, p, oob, 0)
   190  		if err != nil {
   191  			// TODO(dfc) should n and oobn be set to 0
   192  			if err == syscall.EAGAIN && fd.pd.pollable() {
   193  				if err = fd.pd.waitRead(fd.isFile); err == nil {
   194  					continue
   195  				}
   196  			}
   197  		}
   198  		err = fd.eofError(n, err)
   199  		return n, oobn, flags, sa, err
   200  	}
   201  }
   202  
   203  // Write implements io.Writer.
   204  func (fd *FD) Write(p []byte) (int, error) {
   205  	if err := fd.writeLock(); err != nil {
   206  		return 0, err
   207  	}
   208  	defer fd.writeUnlock()
   209  	if err := fd.pd.prepareWrite(fd.isFile); err != nil {
   210  		return 0, err
   211  	}
   212  	var nn int
   213  	for {
   214  		max := len(p)
   215  		if fd.IsStream && max-nn > maxRW {
   216  			max = nn + maxRW
   217  		}
   218  		n, err := syscall.Write(fd.Sysfd, p[nn:max])
   219  		if n > 0 {
   220  			nn += n
   221  		}
   222  		if nn == len(p) {
   223  			return nn, err
   224  		}
   225  		if err == syscall.EAGAIN && fd.pd.pollable() {
   226  			if err = fd.pd.waitWrite(fd.isFile); err == nil {
   227  				continue
   228  			}
   229  		}
   230  		if err != nil {
   231  			return nn, err
   232  		}
   233  		if n == 0 {
   234  			return nn, io.ErrUnexpectedEOF
   235  		}
   236  	}
   237  }
   238  
   239  // Pwrite wraps the pwrite system call.
   240  func (fd *FD) Pwrite(p []byte, off int64) (int, error) {
   241  	// Call incref, not writeLock, because since pwrite specifies the
   242  	// offset it is independent from other writes.
   243  	// Similarly, using the poller doesn't make sense for pwrite.
   244  	if err := fd.incref(); err != nil {
   245  		return 0, err
   246  	}
   247  	defer fd.decref()
   248  	var nn int
   249  	for {
   250  		max := len(p)
   251  		if fd.IsStream && max-nn > maxRW {
   252  			max = nn + maxRW
   253  		}
   254  		n, err := syscall.Pwrite(fd.Sysfd, p[nn:max], off+int64(nn))
   255  		if n > 0 {
   256  			nn += n
   257  		}
   258  		if nn == len(p) {
   259  			return nn, err
   260  		}
   261  		if err != nil {
   262  			return nn, err
   263  		}
   264  		if n == 0 {
   265  			return nn, io.ErrUnexpectedEOF
   266  		}
   267  	}
   268  }
   269  
   270  // WriteTo wraps the sendto network call.
   271  func (fd *FD) WriteTo(p []byte, sa syscall.Sockaddr) (int, error) {
   272  	if err := fd.writeLock(); err != nil {
   273  		return 0, err
   274  	}
   275  	defer fd.writeUnlock()
   276  	if err := fd.pd.prepareWrite(fd.isFile); err != nil {
   277  		return 0, err
   278  	}
   279  	for {
   280  		err := syscall.Sendto(fd.Sysfd, p, 0, sa)
   281  		if err == syscall.EAGAIN && fd.pd.pollable() {
   282  			if err = fd.pd.waitWrite(fd.isFile); err == nil {
   283  				continue
   284  			}
   285  		}
   286  		if err != nil {
   287  			return 0, err
   288  		}
   289  		return len(p), nil
   290  	}
   291  }
   292  
   293  // WriteMsg wraps the sendmsg network call.
   294  func (fd *FD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (int, int, error) {
   295  	if err := fd.writeLock(); err != nil {
   296  		return 0, 0, err
   297  	}
   298  	defer fd.writeUnlock()
   299  	if err := fd.pd.prepareWrite(fd.isFile); err != nil {
   300  		return 0, 0, err
   301  	}
   302  	for {
   303  		n, err := syscall.SendmsgN(fd.Sysfd, p, oob, sa, 0)
   304  		if err == syscall.EAGAIN && fd.pd.pollable() {
   305  			if err = fd.pd.waitWrite(fd.isFile); err == nil {
   306  				continue
   307  			}
   308  		}
   309  		if err != nil {
   310  			return n, 0, err
   311  		}
   312  		return n, len(oob), err
   313  	}
   314  }
   315  
   316  // Accept wraps the accept network call.
   317  func (fd *FD) Accept() (int, syscall.Sockaddr, string, error) {
   318  	if err := fd.readLock(); err != nil {
   319  		return -1, nil, "", err
   320  	}
   321  	defer fd.readUnlock()
   322  
   323  	if err := fd.pd.prepareRead(fd.isFile); err != nil {
   324  		return -1, nil, "", err
   325  	}
   326  	for {
   327  		s, rsa, errcall, err := accept(fd.Sysfd)
   328  		if err == nil {
   329  			return s, rsa, "", err
   330  		}
   331  		switch err {
   332  		case syscall.EAGAIN:
   333  			if fd.pd.pollable() {
   334  				if err = fd.pd.waitRead(fd.isFile); err == nil {
   335  					continue
   336  				}
   337  			}
   338  		case syscall.ECONNABORTED:
   339  			// This means that a socket on the listen
   340  			// queue was closed before we Accept()ed it;
   341  			// it's a silly error, so try again.
   342  			continue
   343  		}
   344  		return -1, nil, errcall, err
   345  	}
   346  }
   347  
   348  // Seek wraps syscall.Seek.
   349  func (fd *FD) Seek(offset int64, whence int) (int64, error) {
   350  	if err := fd.incref(); err != nil {
   351  		return 0, err
   352  	}
   353  	defer fd.decref()
   354  	return syscall.Seek(fd.Sysfd, offset, whence)
   355  }
   356  
   357  // ReadDirent wraps syscall.ReadDirent.
   358  // We treat this like an ordinary system call rather than a call
   359  // that tries to fill the buffer.
   360  func (fd *FD) ReadDirent(buf []byte) (int, error) {
   361  	if err := fd.incref(); err != nil {
   362  		return 0, err
   363  	}
   364  	defer fd.decref()
   365  	for {
   366  		n, err := syscall.ReadDirent(fd.Sysfd, buf)
   367  		if err != nil {
   368  			n = 0
   369  			if err == syscall.EAGAIN && fd.pd.pollable() {
   370  				if err = fd.pd.waitRead(fd.isFile); err == nil {
   371  					continue
   372  				}
   373  			}
   374  		}
   375  		// Do not call eofError; caller does not expect to see io.EOF.
   376  		return n, err
   377  	}
   378  }
   379  
   380  // Fchdir wraps syscall.Fchdir.
   381  func (fd *FD) Fchdir() error {
   382  	if err := fd.incref(); err != nil {
   383  		return err
   384  	}
   385  	defer fd.decref()
   386  	return syscall.Fchdir(fd.Sysfd)
   387  }
   388  
   389  // Fstat wraps syscall.Fstat
   390  func (fd *FD) Fstat(s *syscall.Stat_t) error {
   391  	if err := fd.incref(); err != nil {
   392  		return err
   393  	}
   394  	defer fd.decref()
   395  	return syscall.Fstat(fd.Sysfd, s)
   396  }
   397  
   398  // On Unix variants only, expose the IO event for the net code.
   399  
   400  // WaitWrite waits until data can be read from fd.
   401  func (fd *FD) WaitWrite() error {
   402  	return fd.pd.waitWrite(fd.isFile)
   403  }
   404  
   405  // RawControl invokes the user-defined function f for a non-IO
   406  // operation.
   407  func (fd *FD) RawControl(f func(uintptr)) error {
   408  	if err := fd.incref(); err != nil {
   409  		return err
   410  	}
   411  	defer fd.decref()
   412  	f(uintptr(fd.Sysfd))
   413  	return nil
   414  }
   415  
   416  // RawRead invokes the user-defined function f for a read operation.
   417  func (fd *FD) RawRead(f func(uintptr) bool) error {
   418  	if err := fd.readLock(); err != nil {
   419  		return err
   420  	}
   421  	defer fd.readUnlock()
   422  	if err := fd.pd.prepareRead(fd.isFile); err != nil {
   423  		return err
   424  	}
   425  	for {
   426  		if f(uintptr(fd.Sysfd)) {
   427  			return nil
   428  		}
   429  		if err := fd.pd.waitRead(fd.isFile); err != nil {
   430  			return err
   431  		}
   432  	}
   433  }
   434  
   435  // RawWrite invokes the user-defined function f for a write operation.
   436  func (fd *FD) RawWrite(f func(uintptr) bool) error {
   437  	if err := fd.writeLock(); err != nil {
   438  		return err
   439  	}
   440  	defer fd.writeUnlock()
   441  	if err := fd.pd.prepareWrite(fd.isFile); err != nil {
   442  		return err
   443  	}
   444  	for {
   445  		if f(uintptr(fd.Sysfd)) {
   446  			return nil
   447  		}
   448  		if err := fd.pd.waitWrite(fd.isFile); err != nil {
   449  			return err
   450  		}
   451  	}
   452  }