github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/net/fd_unix.go (about)

     1  // Copyright 2009 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 net
     8  
     9  import (
    10  	"context"
    11  	"io"
    12  	"os"
    13  	"runtime"
    14  	"sync/atomic"
    15  	"syscall"
    16  )
    17  
    18  // Network file descriptor.
    19  type netFD struct {
    20  	// locking/lifetime of sysfd + serialize access to Read and Write methods
    21  	fdmu fdMutex
    22  
    23  	// immutable until Close
    24  	sysfd       int
    25  	family      int
    26  	sotype      int
    27  	isStream    bool
    28  	isConnected bool
    29  	net         string
    30  	laddr       Addr
    31  	raddr       Addr
    32  
    33  	// writev cache.
    34  	iovecs *[]syscall.Iovec
    35  
    36  	// wait server
    37  	pd pollDesc
    38  }
    39  
    40  func sysInit() {
    41  }
    42  
    43  func newFD(sysfd, family, sotype int, net string) (*netFD, error) {
    44  	return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net, isStream: sotype == syscall.SOCK_STREAM}, nil
    45  }
    46  
    47  func (fd *netFD) init() error {
    48  	if err := fd.pd.init(fd); err != nil {
    49  		return err
    50  	}
    51  	return nil
    52  }
    53  
    54  func (fd *netFD) setAddr(laddr, raddr Addr) {
    55  	fd.laddr = laddr
    56  	fd.raddr = raddr
    57  	runtime.SetFinalizer(fd, (*netFD).Close)
    58  }
    59  
    60  func (fd *netFD) name() string {
    61  	var ls, rs string
    62  	if fd.laddr != nil {
    63  		ls = fd.laddr.String()
    64  	}
    65  	if fd.raddr != nil {
    66  		rs = fd.raddr.String()
    67  	}
    68  	return fd.net + ":" + ls + "->" + rs
    69  }
    70  
    71  func (fd *netFD) connect(ctx context.Context, la, ra syscall.Sockaddr) (ret error) {
    72  	// Do not need to call fd.writeLock here,
    73  	// because fd is not yet accessible to user,
    74  	// so no concurrent operations are possible.
    75  	switch err := connectFunc(fd.sysfd, ra); err {
    76  	case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
    77  	case nil, syscall.EISCONN:
    78  		select {
    79  		case <-ctx.Done():
    80  			return mapErr(ctx.Err())
    81  		default:
    82  		}
    83  		if err := fd.init(); err != nil {
    84  			return err
    85  		}
    86  		return nil
    87  	case syscall.EINVAL:
    88  		// On Solaris we can see EINVAL if the socket has
    89  		// already been accepted and closed by the server.
    90  		// Treat this as a successful connection--writes to
    91  		// the socket will see EOF.  For details and a test
    92  		// case in C see https://golang.org/issue/6828.
    93  		if runtime.GOOS == "solaris" {
    94  			return nil
    95  		}
    96  		fallthrough
    97  	default:
    98  		return os.NewSyscallError("connect", err)
    99  	}
   100  	if err := fd.init(); err != nil {
   101  		return err
   102  	}
   103  	if deadline, _ := ctx.Deadline(); !deadline.IsZero() {
   104  		fd.setWriteDeadline(deadline)
   105  		defer fd.setWriteDeadline(noDeadline)
   106  	}
   107  
   108  	// Start the "interrupter" goroutine, if this context might be canceled.
   109  	// (The background context cannot)
   110  	//
   111  	// The interrupter goroutine waits for the context to be done and
   112  	// interrupts the dial (by altering the fd's write deadline, which
   113  	// wakes up waitWrite).
   114  	if ctx != context.Background() {
   115  		// Wait for the interrupter goroutine to exit before returning
   116  		// from connect.
   117  		done := make(chan struct{})
   118  		interruptRes := make(chan error)
   119  		defer func() {
   120  			close(done)
   121  			if ctxErr := <-interruptRes; ctxErr != nil && ret == nil {
   122  				// The interrupter goroutine called setWriteDeadline,
   123  				// but the connect code below had returned from
   124  				// waitWrite already and did a successful connect (ret
   125  				// == nil). Because we've now poisoned the connection
   126  				// by making it unwritable, don't return a successful
   127  				// dial. This was issue 16523.
   128  				ret = ctxErr
   129  				fd.Close() // prevent a leak
   130  			}
   131  		}()
   132  		go func() {
   133  			select {
   134  			case <-ctx.Done():
   135  				// Force the runtime's poller to immediately give up
   136  				// waiting for writability, unblocking waitWrite
   137  				// below.
   138  				fd.setWriteDeadline(aLongTimeAgo)
   139  				testHookCanceledDial()
   140  				interruptRes <- ctx.Err()
   141  			case <-done:
   142  				interruptRes <- nil
   143  			}
   144  		}()
   145  	}
   146  
   147  	for {
   148  		// Performing multiple connect system calls on a
   149  		// non-blocking socket under Unix variants does not
   150  		// necessarily result in earlier errors being
   151  		// returned. Instead, once runtime-integrated network
   152  		// poller tells us that the socket is ready, get the
   153  		// SO_ERROR socket option to see if the connection
   154  		// succeeded or failed. See issue 7474 for further
   155  		// details.
   156  		if err := fd.pd.waitWrite(); err != nil {
   157  			select {
   158  			case <-ctx.Done():
   159  				return mapErr(ctx.Err())
   160  			default:
   161  			}
   162  			return err
   163  		}
   164  		nerr, err := getsockoptIntFunc(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
   165  		if err != nil {
   166  			return os.NewSyscallError("getsockopt", err)
   167  		}
   168  		switch err := syscall.Errno(nerr); err {
   169  		case syscall.EINPROGRESS, syscall.EALREADY, syscall.EINTR:
   170  		case syscall.Errno(0), syscall.EISCONN:
   171  			if runtime.GOOS != "darwin" {
   172  				return nil
   173  			}
   174  			// See golang.org/issue/14548.
   175  			// On Darwin, multiple connect system calls on
   176  			// a non-blocking socket never harm SO_ERROR.
   177  			switch err := connectFunc(fd.sysfd, ra); err {
   178  			case nil, syscall.EISCONN:
   179  				return nil
   180  			}
   181  		default:
   182  			return os.NewSyscallError("getsockopt", err)
   183  		}
   184  	}
   185  }
   186  
   187  func (fd *netFD) destroy() {
   188  	// Poller may want to unregister fd in readiness notification mechanism,
   189  	// so this must be executed before closeFunc.
   190  	fd.pd.close()
   191  	closeFunc(fd.sysfd)
   192  	fd.sysfd = -1
   193  	runtime.SetFinalizer(fd, nil)
   194  }
   195  
   196  func (fd *netFD) Close() error {
   197  	if !fd.fdmu.increfAndClose() {
   198  		return errClosing
   199  	}
   200  	// Unblock any I/O.  Once it all unblocks and returns,
   201  	// so that it cannot be referring to fd.sysfd anymore,
   202  	// the final decref will close fd.sysfd. This should happen
   203  	// fairly quickly, since all the I/O is non-blocking, and any
   204  	// attempts to block in the pollDesc will return errClosing.
   205  	fd.pd.evict()
   206  	fd.decref()
   207  	return nil
   208  }
   209  
   210  func (fd *netFD) shutdown(how int) error {
   211  	if err := fd.incref(); err != nil {
   212  		return err
   213  	}
   214  	defer fd.decref()
   215  	return os.NewSyscallError("shutdown", syscall.Shutdown(fd.sysfd, how))
   216  }
   217  
   218  func (fd *netFD) closeRead() error {
   219  	return fd.shutdown(syscall.SHUT_RD)
   220  }
   221  
   222  func (fd *netFD) closeWrite() error {
   223  	return fd.shutdown(syscall.SHUT_WR)
   224  }
   225  
   226  func (fd *netFD) Read(p []byte) (n int, err error) {
   227  	if err := fd.readLock(); err != nil {
   228  		return 0, err
   229  	}
   230  	defer fd.readUnlock()
   231  	if len(p) == 0 {
   232  		// If the caller wanted a zero byte read, return immediately
   233  		// without trying. (But after acquiring the readLock.) Otherwise
   234  		// syscall.Read returns 0, nil and eofError turns that into
   235  		// io.EOF.
   236  		// TODO(bradfitz): make it wait for readability? (Issue 15735)
   237  		return 0, nil
   238  	}
   239  	if err := fd.pd.prepareRead(); err != nil {
   240  		return 0, err
   241  	}
   242  	if fd.isStream && len(p) > 1<<30 {
   243  		p = p[:1<<30]
   244  	}
   245  	for {
   246  		n, err = syscall.Read(fd.sysfd, p)
   247  		if err != nil {
   248  			n = 0
   249  			if err == syscall.EAGAIN {
   250  				if err = fd.pd.waitRead(); err == nil {
   251  					continue
   252  				}
   253  			}
   254  		}
   255  		err = fd.eofError(n, err)
   256  		break
   257  	}
   258  	if _, ok := err.(syscall.Errno); ok {
   259  		err = os.NewSyscallError("read", err)
   260  	}
   261  	return
   262  }
   263  
   264  func (fd *netFD) readFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
   265  	if err := fd.readLock(); err != nil {
   266  		return 0, nil, err
   267  	}
   268  	defer fd.readUnlock()
   269  	if err := fd.pd.prepareRead(); err != nil {
   270  		return 0, nil, err
   271  	}
   272  	for {
   273  		n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
   274  		if err != nil {
   275  			n = 0
   276  			if err == syscall.EAGAIN {
   277  				if err = fd.pd.waitRead(); err == nil {
   278  					continue
   279  				}
   280  			}
   281  		}
   282  		err = fd.eofError(n, err)
   283  		break
   284  	}
   285  	if _, ok := err.(syscall.Errno); ok {
   286  		err = os.NewSyscallError("recvfrom", err)
   287  	}
   288  	return
   289  }
   290  
   291  func (fd *netFD) readMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
   292  	if err := fd.readLock(); err != nil {
   293  		return 0, 0, 0, nil, err
   294  	}
   295  	defer fd.readUnlock()
   296  	if err := fd.pd.prepareRead(); err != nil {
   297  		return 0, 0, 0, nil, err
   298  	}
   299  	for {
   300  		n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
   301  		if err != nil {
   302  			// TODO(dfc) should n and oobn be set to 0
   303  			if err == syscall.EAGAIN {
   304  				if err = fd.pd.waitRead(); err == nil {
   305  					continue
   306  				}
   307  			}
   308  		}
   309  		err = fd.eofError(n, err)
   310  		break
   311  	}
   312  	if _, ok := err.(syscall.Errno); ok {
   313  		err = os.NewSyscallError("recvmsg", err)
   314  	}
   315  	return
   316  }
   317  
   318  func (fd *netFD) Write(p []byte) (nn int, err error) {
   319  	if err := fd.writeLock(); err != nil {
   320  		return 0, err
   321  	}
   322  	defer fd.writeUnlock()
   323  	if err := fd.pd.prepareWrite(); err != nil {
   324  		return 0, err
   325  	}
   326  	for {
   327  		var n int
   328  		max := len(p)
   329  		if fd.isStream && max-nn > 1<<30 {
   330  			max = nn + 1<<30
   331  		}
   332  		n, err = syscall.Write(fd.sysfd, p[nn:max])
   333  		if n > 0 {
   334  			nn += n
   335  		}
   336  		if nn == len(p) {
   337  			break
   338  		}
   339  		if err == syscall.EAGAIN {
   340  			if err = fd.pd.waitWrite(); err == nil {
   341  				continue
   342  			}
   343  		}
   344  		if err != nil {
   345  			break
   346  		}
   347  		if n == 0 {
   348  			err = io.ErrUnexpectedEOF
   349  			break
   350  		}
   351  	}
   352  	if _, ok := err.(syscall.Errno); ok {
   353  		err = os.NewSyscallError("write", err)
   354  	}
   355  	return nn, err
   356  }
   357  
   358  func (fd *netFD) writeTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
   359  	if err := fd.writeLock(); err != nil {
   360  		return 0, err
   361  	}
   362  	defer fd.writeUnlock()
   363  	if err := fd.pd.prepareWrite(); err != nil {
   364  		return 0, err
   365  	}
   366  	for {
   367  		err = syscall.Sendto(fd.sysfd, p, 0, sa)
   368  		if err == syscall.EAGAIN {
   369  			if err = fd.pd.waitWrite(); err == nil {
   370  				continue
   371  			}
   372  		}
   373  		break
   374  	}
   375  	if err == nil {
   376  		n = len(p)
   377  	}
   378  	if _, ok := err.(syscall.Errno); ok {
   379  		err = os.NewSyscallError("sendto", err)
   380  	}
   381  	return
   382  }
   383  
   384  func (fd *netFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
   385  	if err := fd.writeLock(); err != nil {
   386  		return 0, 0, err
   387  	}
   388  	defer fd.writeUnlock()
   389  	if err := fd.pd.prepareWrite(); err != nil {
   390  		return 0, 0, err
   391  	}
   392  	for {
   393  		n, err = syscall.SendmsgN(fd.sysfd, p, oob, sa, 0)
   394  		if err == syscall.EAGAIN {
   395  			if err = fd.pd.waitWrite(); err == nil {
   396  				continue
   397  			}
   398  		}
   399  		break
   400  	}
   401  	if err == nil {
   402  		oobn = len(oob)
   403  	}
   404  	if _, ok := err.(syscall.Errno); ok {
   405  		err = os.NewSyscallError("sendmsg", err)
   406  	}
   407  	return
   408  }
   409  
   410  func (fd *netFD) accept() (netfd *netFD, err error) {
   411  	if err := fd.readLock(); err != nil {
   412  		return nil, err
   413  	}
   414  	defer fd.readUnlock()
   415  
   416  	var s int
   417  	var rsa syscall.Sockaddr
   418  	if err = fd.pd.prepareRead(); err != nil {
   419  		return nil, err
   420  	}
   421  	for {
   422  		s, rsa, err = accept(fd.sysfd)
   423  		if err != nil {
   424  			nerr, ok := err.(*os.SyscallError)
   425  			if !ok {
   426  				return nil, err
   427  			}
   428  			switch nerr.Err {
   429  			case syscall.EAGAIN:
   430  				if err = fd.pd.waitRead(); err == nil {
   431  					continue
   432  				}
   433  			case syscall.ECONNABORTED:
   434  				// This means that a socket on the
   435  				// listen queue was closed before we
   436  				// Accept()ed it; it's a silly error,
   437  				// so try again.
   438  				continue
   439  			}
   440  			return nil, err
   441  		}
   442  		break
   443  	}
   444  
   445  	if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil {
   446  		closeFunc(s)
   447  		return nil, err
   448  	}
   449  	if err = netfd.init(); err != nil {
   450  		fd.Close()
   451  		return nil, err
   452  	}
   453  	lsa, _ := syscall.Getsockname(netfd.sysfd)
   454  	netfd.setAddr(netfd.addrFunc()(lsa), netfd.addrFunc()(rsa))
   455  	return netfd, nil
   456  }
   457  
   458  // tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used.
   459  // If the kernel doesn't support it, this is set to 0.
   460  var tryDupCloexec = int32(1)
   461  
   462  func dupCloseOnExec(fd int) (newfd int, err error) {
   463  	if atomic.LoadInt32(&tryDupCloexec) == 1 {
   464  		r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0)
   465  		if runtime.GOOS == "darwin" && e1 == syscall.EBADF {
   466  			// On OS X 10.6 and below (but we only support
   467  			// >= 10.6), F_DUPFD_CLOEXEC is unsupported
   468  			// and fcntl there falls back (undocumented)
   469  			// to doing an ioctl instead, returning EBADF
   470  			// in this case because fd is not of the
   471  			// expected device fd type. Treat it as
   472  			// EINVAL instead, so we fall back to the
   473  			// normal dup path.
   474  			// TODO: only do this on 10.6 if we can detect 10.6
   475  			// cheaply.
   476  			e1 = syscall.EINVAL
   477  		}
   478  		switch e1 {
   479  		case 0:
   480  			return int(r0), nil
   481  		case syscall.EINVAL:
   482  			// Old kernel. Fall back to the portable way
   483  			// from now on.
   484  			atomic.StoreInt32(&tryDupCloexec, 0)
   485  		default:
   486  			return -1, os.NewSyscallError("fcntl", e1)
   487  		}
   488  	}
   489  	return dupCloseOnExecOld(fd)
   490  }
   491  
   492  // dupCloseOnExecUnixOld is the traditional way to dup an fd and
   493  // set its O_CLOEXEC bit, using two system calls.
   494  func dupCloseOnExecOld(fd int) (newfd int, err error) {
   495  	syscall.ForkLock.RLock()
   496  	defer syscall.ForkLock.RUnlock()
   497  	newfd, err = syscall.Dup(fd)
   498  	if err != nil {
   499  		return -1, os.NewSyscallError("dup", err)
   500  	}
   501  	syscall.CloseOnExec(newfd)
   502  	return
   503  }
   504  
   505  func (fd *netFD) dup() (f *os.File, err error) {
   506  	ns, err := dupCloseOnExec(fd.sysfd)
   507  	if err != nil {
   508  		return nil, err
   509  	}
   510  
   511  	// We want blocking mode for the new fd, hence the double negative.
   512  	// This also puts the old fd into blocking mode, meaning that
   513  	// I/O will block the thread instead of letting us use the epoll server.
   514  	// Everything will still work, just with more threads.
   515  	if err = syscall.SetNonblock(ns, false); err != nil {
   516  		return nil, os.NewSyscallError("setnonblock", err)
   517  	}
   518  
   519  	return os.NewFile(uintptr(ns), fd.name()), nil
   520  }