Home | History | Annotate | Download | only in poll
      1 // Copyright 2013 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 // This file implements sysSocket and accept for platforms that
      6 // provide a fast path for setting SetNonblock and CloseOnExec.
      7 
      8 // +build dragonfly freebsd linux
      9 
     10 package poll
     11 
     12 import "syscall"
     13 
     14 // Wrapper around the accept system call that marks the returned file
     15 // descriptor as nonblocking and close-on-exec.
     16 func accept(s int) (int, syscall.Sockaddr, string, error) {
     17 	ns, sa, err := Accept4Func(s, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC)
     18 	// On Linux the accept4 system call was introduced in 2.6.28
     19 	// kernel and on FreeBSD it was introduced in 10 kernel. If we
     20 	// get an ENOSYS error on both Linux and FreeBSD, or EINVAL
     21 	// error on Linux, fall back to using accept.
     22 	switch err {
     23 	case nil:
     24 		return ns, sa, "", nil
     25 	default: // errors other than the ones listed
     26 		return -1, sa, "accept4", err
     27 	case syscall.ENOSYS: // syscall missing
     28 	case syscall.EINVAL: // some Linux use this instead of ENOSYS
     29 	case syscall.EACCES: // some Linux use this instead of ENOSYS
     30 	case syscall.EFAULT: // some Linux use this instead of ENOSYS
     31 	}
     32 
     33 	// See ../syscall/exec_unix.go for description of ForkLock.
     34 	// It is probably okay to hold the lock across syscall.Accept
     35 	// because we have put fd.sysfd into non-blocking mode.
     36 	// However, a call to the File method will put it back into
     37 	// blocking mode. We can't take that risk, so no use of ForkLock here.
     38 	ns, sa, err = AcceptFunc(s)
     39 	if err == nil {
     40 		syscall.CloseOnExec(ns)
     41 	}
     42 	if err != nil {
     43 		return -1, nil, "accept", err
     44 	}
     45 	if err = syscall.SetNonblock(ns, true); err != nil {
     46 		CloseFunc(ns)
     47 		return -1, nil, "setnonblock", err
     48 	}
     49 	return ns, sa, "", nil
     50 }
     51