github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/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 netbsd openbsd
     6  
     7  package net
     8  
     9  import (
    10  	"io"
    11  	"os"
    12  	"runtime"
    13  	"sync/atomic"
    14  	"syscall"
    15  	"time"
    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  	isConnected bool
    28  	net         string
    29  	laddr       Addr
    30  	raddr       Addr
    31  
    32  	// wait server
    33  	pd pollDesc
    34  }
    35  
    36  func sysInit() {
    37  }
    38  
    39  func dial(network string, ra Addr, dialer func(time.Time) (Conn, error), deadline time.Time) (Conn, error) {
    40  	return dialer(deadline)
    41  }
    42  
    43  func newFD(sysfd, family, sotype int, net string) (*netFD, error) {
    44  	return &netFD{sysfd: sysfd, family: family, sotype: sotype, net: net}, 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(la, ra syscall.Sockaddr) 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  	if err := fd.pd.PrepareWrite(); err != nil {
    76  		return err
    77  	}
    78  	for {
    79  		err := syscall.Connect(fd.sysfd, ra)
    80  		if err == nil || err == syscall.EISCONN {
    81  			break
    82  		}
    83  		if err != syscall.EINPROGRESS && err != syscall.EALREADY && err != syscall.EINTR {
    84  			return err
    85  		}
    86  		if err = fd.pd.WaitWrite(); err != nil {
    87  			return err
    88  		}
    89  	}
    90  	return nil
    91  }
    92  
    93  func (fd *netFD) destroy() {
    94  	// Poller may want to unregister fd in readiness notification mechanism,
    95  	// so this must be executed before closesocket.
    96  	fd.pd.Close()
    97  	closesocket(fd.sysfd)
    98  	fd.sysfd = -1
    99  	runtime.SetFinalizer(fd, nil)
   100  }
   101  
   102  // Add a reference to this fd.
   103  // Returns an error if the fd cannot be used.
   104  func (fd *netFD) incref() error {
   105  	if !fd.fdmu.Incref() {
   106  		return errClosing
   107  	}
   108  	return nil
   109  }
   110  
   111  // Remove a reference to this FD and close if we've been asked to do so
   112  // (and there are no references left).
   113  func (fd *netFD) decref() {
   114  	if fd.fdmu.Decref() {
   115  		fd.destroy()
   116  	}
   117  }
   118  
   119  // Add a reference to this fd and lock for reading.
   120  // Returns an error if the fd cannot be used.
   121  func (fd *netFD) readLock() error {
   122  	if !fd.fdmu.RWLock(true) {
   123  		return errClosing
   124  	}
   125  	return nil
   126  }
   127  
   128  // Unlock for reading and remove a reference to this FD.
   129  func (fd *netFD) readUnlock() {
   130  	if fd.fdmu.RWUnlock(true) {
   131  		fd.destroy()
   132  	}
   133  }
   134  
   135  // Add a reference to this fd and lock for writing.
   136  // Returns an error if the fd cannot be used.
   137  func (fd *netFD) writeLock() error {
   138  	if !fd.fdmu.RWLock(false) {
   139  		return errClosing
   140  	}
   141  	return nil
   142  }
   143  
   144  // Unlock for writing and remove a reference to this FD.
   145  func (fd *netFD) writeUnlock() {
   146  	if fd.fdmu.RWUnlock(false) {
   147  		fd.destroy()
   148  	}
   149  }
   150  
   151  func (fd *netFD) Close() error {
   152  	fd.pd.Lock() // needed for both fd.incref(true) and pollDesc.Evict
   153  	if !fd.fdmu.IncrefAndClose() {
   154  		fd.pd.Unlock()
   155  		return errClosing
   156  	}
   157  	// Unblock any I/O.  Once it all unblocks and returns,
   158  	// so that it cannot be referring to fd.sysfd anymore,
   159  	// the final decref will close fd.sysfd.  This should happen
   160  	// fairly quickly, since all the I/O is non-blocking, and any
   161  	// attempts to block in the pollDesc will return errClosing.
   162  	doWakeup := fd.pd.Evict()
   163  	fd.pd.Unlock()
   164  	fd.decref()
   165  	if doWakeup {
   166  		fd.pd.Wakeup()
   167  	}
   168  	return nil
   169  }
   170  
   171  func (fd *netFD) shutdown(how int) error {
   172  	if err := fd.incref(); err != nil {
   173  		return err
   174  	}
   175  	defer fd.decref()
   176  	err := syscall.Shutdown(fd.sysfd, how)
   177  	if err != nil {
   178  		return &OpError{"shutdown", fd.net, fd.laddr, err}
   179  	}
   180  	return nil
   181  }
   182  
   183  func (fd *netFD) CloseRead() error {
   184  	return fd.shutdown(syscall.SHUT_RD)
   185  }
   186  
   187  func (fd *netFD) CloseWrite() error {
   188  	return fd.shutdown(syscall.SHUT_WR)
   189  }
   190  
   191  func (fd *netFD) Read(p []byte) (n int, err error) {
   192  	if err := fd.readLock(); err != nil {
   193  		return 0, err
   194  	}
   195  	defer fd.readUnlock()
   196  	if err := fd.pd.PrepareRead(); err != nil {
   197  		return 0, &OpError{"read", fd.net, fd.raddr, err}
   198  	}
   199  	for {
   200  		n, err = syscall.Read(int(fd.sysfd), p)
   201  		if err != nil {
   202  			n = 0
   203  			if err == syscall.EAGAIN {
   204  				if err = fd.pd.WaitRead(); err == nil {
   205  					continue
   206  				}
   207  			}
   208  		}
   209  		err = chkReadErr(n, err, fd)
   210  		break
   211  	}
   212  	if err != nil && err != io.EOF {
   213  		err = &OpError{"read", fd.net, fd.raddr, err}
   214  	}
   215  	return
   216  }
   217  
   218  func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
   219  	if err := fd.readLock(); err != nil {
   220  		return 0, nil, err
   221  	}
   222  	defer fd.readUnlock()
   223  	if err := fd.pd.PrepareRead(); err != nil {
   224  		return 0, nil, &OpError{"read", fd.net, fd.laddr, err}
   225  	}
   226  	for {
   227  		n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
   228  		if err != nil {
   229  			n = 0
   230  			if err == syscall.EAGAIN {
   231  				if err = fd.pd.WaitRead(); err == nil {
   232  					continue
   233  				}
   234  			}
   235  		}
   236  		err = chkReadErr(n, err, fd)
   237  		break
   238  	}
   239  	if err != nil && err != io.EOF {
   240  		err = &OpError{"read", fd.net, fd.laddr, err}
   241  	}
   242  	return
   243  }
   244  
   245  func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
   246  	if err := fd.readLock(); err != nil {
   247  		return 0, 0, 0, nil, err
   248  	}
   249  	defer fd.readUnlock()
   250  	if err := fd.pd.PrepareRead(); err != nil {
   251  		return 0, 0, 0, nil, &OpError{"read", fd.net, fd.laddr, err}
   252  	}
   253  	for {
   254  		n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
   255  		if err != nil {
   256  			// TODO(dfc) should n and oobn be set to 0
   257  			if err == syscall.EAGAIN {
   258  				if err = fd.pd.WaitRead(); err == nil {
   259  					continue
   260  				}
   261  			}
   262  		}
   263  		err = chkReadErr(n, err, fd)
   264  		break
   265  	}
   266  	if err != nil && err != io.EOF {
   267  		err = &OpError{"read", fd.net, fd.laddr, err}
   268  	}
   269  	return
   270  }
   271  
   272  func chkReadErr(n int, err error, fd *netFD) error {
   273  	if n == 0 && err == nil && fd.sotype != syscall.SOCK_DGRAM && fd.sotype != syscall.SOCK_RAW {
   274  		return io.EOF
   275  	}
   276  	return err
   277  }
   278  
   279  func (fd *netFD) Write(p []byte) (nn int, err error) {
   280  	if err := fd.writeLock(); err != nil {
   281  		return 0, err
   282  	}
   283  	defer fd.writeUnlock()
   284  	if err := fd.pd.PrepareWrite(); err != nil {
   285  		return 0, &OpError{"write", fd.net, fd.raddr, err}
   286  	}
   287  	for {
   288  		var n int
   289  		n, err = syscall.Write(int(fd.sysfd), p[nn:])
   290  		if n > 0 {
   291  			nn += n
   292  		}
   293  		if nn == len(p) {
   294  			break
   295  		}
   296  		if err == syscall.EAGAIN {
   297  			if err = fd.pd.WaitWrite(); err == nil {
   298  				continue
   299  			}
   300  		}
   301  		if err != nil {
   302  			n = 0
   303  			break
   304  		}
   305  		if n == 0 {
   306  			err = io.ErrUnexpectedEOF
   307  			break
   308  		}
   309  	}
   310  	if err != nil {
   311  		err = &OpError{"write", fd.net, fd.raddr, err}
   312  	}
   313  	return nn, err
   314  }
   315  
   316  func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
   317  	if err := fd.writeLock(); err != nil {
   318  		return 0, err
   319  	}
   320  	defer fd.writeUnlock()
   321  	if err := fd.pd.PrepareWrite(); err != nil {
   322  		return 0, &OpError{"write", fd.net, fd.raddr, err}
   323  	}
   324  	for {
   325  		err = syscall.Sendto(fd.sysfd, p, 0, sa)
   326  		if err == syscall.EAGAIN {
   327  			if err = fd.pd.WaitWrite(); err == nil {
   328  				continue
   329  			}
   330  		}
   331  		break
   332  	}
   333  	if err == nil {
   334  		n = len(p)
   335  	} else {
   336  		err = &OpError{"write", fd.net, fd.raddr, err}
   337  	}
   338  	return
   339  }
   340  
   341  func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
   342  	if err := fd.writeLock(); err != nil {
   343  		return 0, 0, err
   344  	}
   345  	defer fd.writeUnlock()
   346  	if err := fd.pd.PrepareWrite(); err != nil {
   347  		return 0, 0, &OpError{"write", fd.net, fd.raddr, err}
   348  	}
   349  	for {
   350  		err = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0)
   351  		if err == syscall.EAGAIN {
   352  			if err = fd.pd.WaitWrite(); err == nil {
   353  				continue
   354  			}
   355  		}
   356  		break
   357  	}
   358  	if err == nil {
   359  		n = len(p)
   360  		oobn = len(oob)
   361  	} else {
   362  		err = &OpError{"write", fd.net, fd.raddr, err}
   363  	}
   364  	return
   365  }
   366  
   367  func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err error) {
   368  	if err := fd.readLock(); err != nil {
   369  		return nil, err
   370  	}
   371  	defer fd.readUnlock()
   372  
   373  	var s int
   374  	var rsa syscall.Sockaddr
   375  	if err = fd.pd.PrepareRead(); err != nil {
   376  		return nil, &OpError{"accept", fd.net, fd.laddr, err}
   377  	}
   378  	for {
   379  		s, rsa, err = accept(fd.sysfd)
   380  		if err != nil {
   381  			if err == syscall.EAGAIN {
   382  				if err = fd.pd.WaitRead(); err == nil {
   383  					continue
   384  				}
   385  			} else if err == syscall.ECONNABORTED {
   386  				// This means that a socket on the listen queue was closed
   387  				// before we Accept()ed it; it's a silly error, so try again.
   388  				continue
   389  			}
   390  			return nil, &OpError{"accept", fd.net, fd.laddr, err}
   391  		}
   392  		break
   393  	}
   394  
   395  	if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil {
   396  		closesocket(s)
   397  		return nil, err
   398  	}
   399  	if err = netfd.init(); err != nil {
   400  		fd.Close()
   401  		return nil, err
   402  	}
   403  	lsa, _ := syscall.Getsockname(netfd.sysfd)
   404  	netfd.setAddr(toAddr(lsa), toAddr(rsa))
   405  	return netfd, nil
   406  }
   407  
   408  // tryDupCloexec indicates whether F_DUPFD_CLOEXEC should be used.
   409  // If the kernel doesn't support it, this is set to 0.
   410  var tryDupCloexec = int32(1)
   411  
   412  func dupCloseOnExec(fd int) (newfd int, err error) {
   413  	if atomic.LoadInt32(&tryDupCloexec) == 1 {
   414  		r0, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd), syscall.F_DUPFD_CLOEXEC, 0)
   415  		if runtime.GOOS == "darwin" && e1 == syscall.EBADF {
   416  			// On OS X 10.6 and below (but we only support
   417  			// >= 10.6), F_DUPFD_CLOEXEC is unsupported
   418  			// and fcntl there falls back (undocumented)
   419  			// to doing an ioctl instead, returning EBADF
   420  			// in this case because fd is not of the
   421  			// expected device fd type.  Treat it as
   422  			// EINVAL instead, so we fall back to the
   423  			// normal dup path.
   424  			// TODO: only do this on 10.6 if we can detect 10.6
   425  			// cheaply.
   426  			e1 = syscall.EINVAL
   427  		}
   428  		switch e1 {
   429  		case 0:
   430  			return int(r0), nil
   431  		case syscall.EINVAL:
   432  			// Old kernel. Fall back to the portable way
   433  			// from now on.
   434  			atomic.StoreInt32(&tryDupCloexec, 0)
   435  		default:
   436  			return -1, e1
   437  		}
   438  	}
   439  	return dupCloseOnExecOld(fd)
   440  }
   441  
   442  // dupCloseOnExecUnixOld is the traditional way to dup an fd and
   443  // set its O_CLOEXEC bit, using two system calls.
   444  func dupCloseOnExecOld(fd int) (newfd int, err error) {
   445  	syscall.ForkLock.RLock()
   446  	defer syscall.ForkLock.RUnlock()
   447  	newfd, err = syscall.Dup(fd)
   448  	if err != nil {
   449  		return -1, err
   450  	}
   451  	syscall.CloseOnExec(newfd)
   452  	return
   453  }
   454  
   455  func (fd *netFD) dup() (f *os.File, err error) {
   456  	ns, err := dupCloseOnExec(fd.sysfd)
   457  	if err != nil {
   458  		syscall.ForkLock.RUnlock()
   459  		return nil, &OpError{"dup", fd.net, fd.laddr, err}
   460  	}
   461  
   462  	// We want blocking mode for the new fd, hence the double negative.
   463  	// This also puts the old fd into blocking mode, meaning that
   464  	// I/O will block the thread instead of letting us use the epoll server.
   465  	// Everything will still work, just with more threads.
   466  	if err = syscall.SetNonblock(ns, false); err != nil {
   467  		return nil, &OpError{"setnonblock", fd.net, fd.laddr, err}
   468  	}
   469  
   470  	return os.NewFile(uintptr(ns), fd.name()), nil
   471  }
   472  
   473  func closesocket(s int) error {
   474  	return syscall.Close(s)
   475  }
   476  
   477  func skipRawSocketTests() (skip bool, skipmsg string, err error) {
   478  	if os.Getuid() != 0 {
   479  		return true, "skipping test; must be root", nil
   480  	}
   481  	return false, "", nil
   482  }