github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/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  
    38  // Init initializes the FD. The Sysfd field should already be set.
    39  // This can be called multiple times on a single FD.
    40  func (fd *FD) Init() error {
    41  	return fd.pd.init(fd)
    42  }
    43  
    44  // Destroy closes the file descriptor. This is called when there are
    45  // no remaining references.
    46  func (fd *FD) destroy() error {
    47  	// Poller may want to unregister fd in readiness notification mechanism,
    48  	// so this must be executed before CloseFunc.
    49  	fd.pd.close()
    50  	err := CloseFunc(fd.Sysfd)
    51  	fd.Sysfd = -1
    52  	return err
    53  }
    54  
    55  // Close closes the FD. The underlying file descriptor is closed by the
    56  // destroy method when there are no remaining references.
    57  func (fd *FD) Close() error {
    58  	if !fd.fdmu.increfAndClose() {
    59  		return ErrClosing
    60  	}
    61  	// Unblock any I/O.  Once it all unblocks and returns,
    62  	// so that it cannot be referring to fd.sysfd anymore,
    63  	// the final decref will close fd.sysfd. This should happen
    64  	// fairly quickly, since all the I/O is non-blocking, and any
    65  	// attempts to block in the pollDesc will return ErrClosing.
    66  	fd.pd.evict()
    67  	// The call to decref will call destroy if there are no other
    68  	// references.
    69  	return fd.decref()
    70  }
    71  
    72  // Shutdown wraps the shutdown call.
    73  func (fd *FD) Shutdown(how int) error {
    74  	if err := fd.incref(); err != nil {
    75  		return err
    76  	}
    77  	defer fd.decref()
    78  	return syscall.Shutdown(fd.Sysfd, how)
    79  }
    80  
    81  // Darwin and FreeBSD can't read or write 2GB+ files at a time,
    82  // even on 64-bit systems.
    83  // The same is true of socket implementations on many systems.
    84  // See golang.org/issue/7812 and golang.org/issue/16266.
    85  // Use 1GB instead of, say, 2GB-1, to keep subsequent reads aligned.
    86  const maxRW = 1 << 30
    87  
    88  // Read implements io.Reader.
    89  func (fd *FD) Read(p []byte) (int, error) {
    90  	if err := fd.readLock(); err != nil {
    91  		return 0, err
    92  	}
    93  	defer fd.readUnlock()
    94  	if len(p) == 0 {
    95  		// If the caller wanted a zero byte read, return immediately
    96  		// without trying (but after acquiring the readLock).
    97  		// Otherwise syscall.Read returns 0, nil which looks like
    98  		// io.EOF.
    99  		// TODO(bradfitz): make it wait for readability? (Issue 15735)
   100  		return 0, nil
   101  	}
   102  	if err := fd.pd.prepareRead(); err != nil {
   103  		return 0, err
   104  	}
   105  	if fd.IsStream && len(p) > maxRW {
   106  		p = p[:maxRW]
   107  	}
   108  	for {
   109  		n, err := syscall.Read(fd.Sysfd, p)
   110  		if err != nil {
   111  			n = 0
   112  			if err == syscall.EAGAIN {
   113  				if err = fd.pd.waitRead(); err == nil {
   114  					continue
   115  				}
   116  			}
   117  		}
   118  		err = fd.eofError(n, err)
   119  		return n, err
   120  	}
   121  }
   122  
   123  // Pread wraps the pread system call.
   124  func (fd *FD) Pread(p []byte, off int64) (int, error) {
   125  	if err := fd.readLock(); err != nil {
   126  		return 0, err
   127  	}
   128  	defer fd.readUnlock()
   129  	if err := fd.pd.prepareRead(); err != nil {
   130  		return 0, err
   131  	}
   132  	if fd.IsStream && len(p) > maxRW {
   133  		p = p[:maxRW]
   134  	}
   135  	for {
   136  		n, err := syscall.Pread(fd.Sysfd, p, off)
   137  		if err != nil {
   138  			n = 0
   139  			if err == syscall.EAGAIN {
   140  				if err = fd.pd.waitRead(); err == nil {
   141  					continue
   142  				}
   143  			}
   144  		}
   145  		err = fd.eofError(n, err)
   146  		return n, err
   147  	}
   148  }
   149  
   150  // RecvFrom wraps the recvfrom network call.
   151  func (fd *FD) RecvFrom(p []byte) (int, syscall.Sockaddr, error) {
   152  	if err := fd.readLock(); err != nil {
   153  		return 0, nil, err
   154  	}
   155  	defer fd.readUnlock()
   156  	if err := fd.pd.prepareRead(); err != nil {
   157  		return 0, nil, err
   158  	}
   159  	for {
   160  		n, sa, err := syscall.Recvfrom(fd.Sysfd, p, 0)
   161  		if err != nil {
   162  			n = 0
   163  			if err == syscall.EAGAIN {
   164  				if err = fd.pd.waitRead(); err == nil {
   165  					continue
   166  				}
   167  			}
   168  		}
   169  		err = fd.eofError(n, err)
   170  		return n, sa, err
   171  	}
   172  }
   173  
   174  // ReadMsg wraps the recvmsg network call.
   175  func (fd *FD) ReadMsg(p []byte, oob []byte) (int, int, int, syscall.Sockaddr, error) {
   176  	if err := fd.readLock(); err != nil {
   177  		return 0, 0, 0, nil, err
   178  	}
   179  	defer fd.readUnlock()
   180  	if err := fd.pd.prepareRead(); err != nil {
   181  		return 0, 0, 0, nil, err
   182  	}
   183  	for {
   184  		n, oobn, flags, sa, err := syscall.Recvmsg(fd.Sysfd, p, oob, 0)
   185  		if err != nil {
   186  			// TODO(dfc) should n and oobn be set to 0
   187  			if err == syscall.EAGAIN {
   188  				if err = fd.pd.waitRead(); err == nil {
   189  					continue
   190  				}
   191  			}
   192  		}
   193  		err = fd.eofError(n, err)
   194  		return n, oobn, flags, sa, err
   195  	}
   196  }
   197  
   198  // Write implements io.Writer.
   199  func (fd *FD) Write(p []byte) (int, error) {
   200  	if err := fd.writeLock(); err != nil {
   201  		return 0, err
   202  	}
   203  	defer fd.writeUnlock()
   204  	if err := fd.pd.prepareWrite(); err != nil {
   205  		return 0, err
   206  	}
   207  	var nn int
   208  	for {
   209  		max := len(p)
   210  		if fd.IsStream && max-nn > maxRW {
   211  			max = nn + maxRW
   212  		}
   213  		n, err := syscall.Write(fd.Sysfd, p[nn:max])
   214  		if n > 0 {
   215  			nn += n
   216  		}
   217  		if nn == len(p) {
   218  			return nn, err
   219  		}
   220  		if err == syscall.EAGAIN {
   221  			if err = fd.pd.waitWrite(); err == nil {
   222  				continue
   223  			}
   224  		}
   225  		if err != nil {
   226  			return nn, err
   227  		}
   228  		if n == 0 {
   229  			return nn, io.ErrUnexpectedEOF
   230  		}
   231  	}
   232  }
   233  
   234  // Pwrite wraps the pwrite system call.
   235  func (fd *FD) Pwrite(p []byte, off int64) (int, error) {
   236  	if err := fd.writeLock(); err != nil {
   237  		return 0, err
   238  	}
   239  	defer fd.writeUnlock()
   240  	if err := fd.pd.prepareWrite(); err != nil {
   241  		return 0, err
   242  	}
   243  	var nn int
   244  	for {
   245  		max := len(p)
   246  		if fd.IsStream && max-nn > maxRW {
   247  			max = nn + maxRW
   248  		}
   249  		n, err := syscall.Pwrite(fd.Sysfd, p[nn:max], off+int64(nn))
   250  		if n > 0 {
   251  			nn += n
   252  		}
   253  		if nn == len(p) {
   254  			return nn, err
   255  		}
   256  		if err == syscall.EAGAIN {
   257  			if err = fd.pd.waitWrite(); err == nil {
   258  				continue
   259  			}
   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(); err != nil {
   277  		return 0, err
   278  	}
   279  	for {
   280  		err := syscall.Sendto(fd.Sysfd, p, 0, sa)
   281  		if err == syscall.EAGAIN {
   282  			if err = fd.pd.waitWrite(); 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(); 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 {
   305  			if err = fd.pd.waitWrite(); 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  // WaitWrite waits until data can be written to fd.
   317  func (fd *FD) WaitWrite() error {
   318  	return fd.pd.waitWrite()
   319  }
   320  
   321  // Accept wraps the accept network call.
   322  func (fd *FD) Accept() (int, syscall.Sockaddr, string, error) {
   323  	if err := fd.readLock(); err != nil {
   324  		return -1, nil, "", err
   325  	}
   326  	defer fd.readUnlock()
   327  
   328  	if err := fd.pd.prepareRead(); err != nil {
   329  		return -1, nil, "", err
   330  	}
   331  	for {
   332  		s, rsa, errcall, err := accept(fd.Sysfd)
   333  		if err == nil {
   334  			return s, rsa, "", err
   335  		}
   336  		switch err {
   337  		case syscall.EAGAIN:
   338  			if err = fd.pd.waitRead(); err == nil {
   339  				continue
   340  			}
   341  		case syscall.ECONNABORTED:
   342  			// This means that a socket on the listen
   343  			// queue was closed before we Accept()ed it;
   344  			// it's a silly error, so try again.
   345  			continue
   346  		}
   347  		return -1, nil, errcall, err
   348  	}
   349  }
   350  
   351  // Seek wraps syscall.Seek.
   352  func (fd *FD) Seek(offset int64, whence int) (int64, error) {
   353  	if err := fd.incref(); err != nil {
   354  		return 0, err
   355  	}
   356  	defer fd.decref()
   357  	return syscall.Seek(fd.Sysfd, offset, whence)
   358  }
   359  
   360  // ReadDirent wraps syscall.ReadDirent.
   361  // We treat this like an ordinary system call rather than a call
   362  // that tries to fill the buffer.
   363  func (fd *FD) ReadDirent(buf []byte) (int, error) {
   364  	if err := fd.incref(); err != nil {
   365  		return 0, err
   366  	}
   367  	defer fd.decref()
   368  	for {
   369  		n, err := syscall.ReadDirent(fd.Sysfd, buf)
   370  		if err != nil {
   371  			n = 0
   372  			if err == syscall.EAGAIN {
   373  				if err = fd.pd.waitRead(); err == nil {
   374  					continue
   375  				}
   376  			}
   377  		}
   378  		// Do not call eofError; caller does not expect to see io.EOF.
   379  		return n, err
   380  	}
   381  }
   382  
   383  // Fchdir wraps syscall.Fchdir.
   384  func (fd *FD) Fchdir() error {
   385  	if err := fd.incref(); err != nil {
   386  		return err
   387  	}
   388  	defer fd.decref()
   389  	return syscall.Fchdir(fd.Sysfd)
   390  }
   391  
   392  // Fstat wraps syscall.Fstat
   393  func (fd *FD) Fstat(s *syscall.Stat_t) error {
   394  	if err := fd.incref(); err != nil {
   395  		return err
   396  	}
   397  	defer fd.decref()
   398  	return syscall.Fstat(fd.Sysfd, s)
   399  }