github.com/mdempsky/go@v0.0.0-20151201204031-5dd372bd1e70/src/net/sock_cloexec.go (about) 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 freebsd linux 9 10 package net 11 12 import ( 13 "os" 14 "syscall" 15 ) 16 17 // Wrapper around the socket system call that marks the returned file 18 // descriptor as nonblocking and close-on-exec. 19 func sysSocket(family, sotype, proto int) (int, error) { 20 s, err := socketFunc(family, sotype|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, proto) 21 // On Linux the SOCK_NONBLOCK and SOCK_CLOEXEC flags were 22 // introduced in 2.6.27 kernel and on FreeBSD both flags were 23 // introduced in 10 kernel. If we get an EINVAL error on Linux 24 // or EPROTONOSUPPORT error on FreeBSD, fall back to using 25 // socket without them. 26 switch err { 27 case nil: 28 return s, nil 29 default: 30 return -1, os.NewSyscallError("socket", err) 31 case syscall.EPROTONOSUPPORT, syscall.EINVAL: 32 } 33 34 // See ../syscall/exec_unix.go for description of ForkLock. 35 syscall.ForkLock.RLock() 36 s, err = socketFunc(family, sotype, proto) 37 if err == nil { 38 syscall.CloseOnExec(s) 39 } 40 syscall.ForkLock.RUnlock() 41 if err != nil { 42 return -1, os.NewSyscallError("socket", err) 43 } 44 if err = syscall.SetNonblock(s, true); err != nil { 45 closeFunc(s) 46 return -1, os.NewSyscallError("setnonblock", err) 47 } 48 return s, nil 49 } 50 51 // Wrapper around the accept system call that marks the returned file 52 // descriptor as nonblocking and close-on-exec. 53 func accept(s int) (int, syscall.Sockaddr, error) { 54 ns, sa, err := accept4Func(s, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC) 55 // On Linux the accept4 system call was introduced in 2.6.28 56 // kernel and on FreeBSD it was introduced in 10 kernel. If we 57 // get an ENOSYS error on both Linux and FreeBSD, or EINVAL 58 // error on Linux, fall back to using accept. 59 switch err { 60 case nil: 61 return ns, sa, nil 62 default: // errors other than the ones listed 63 return -1, sa, os.NewSyscallError("accept4", err) 64 case syscall.ENOSYS: // syscall missing 65 case syscall.EINVAL: // some Linux use this instead of ENOSYS 66 case syscall.EACCES: // some Linux use this instead of ENOSYS 67 case syscall.EFAULT: // some Linux use this instead of ENOSYS 68 } 69 70 // See ../syscall/exec_unix.go for description of ForkLock. 71 // It is probably okay to hold the lock across syscall.Accept 72 // because we have put fd.sysfd into non-blocking mode. 73 // However, a call to the File method will put it back into 74 // blocking mode. We can't take that risk, so no use of ForkLock here. 75 ns, sa, err = acceptFunc(s) 76 if err == nil { 77 syscall.CloseOnExec(ns) 78 } 79 if err != nil { 80 return -1, nil, os.NewSyscallError("accept", err) 81 } 82 if err = syscall.SetNonblock(ns, true); err != nil { 83 closeFunc(ns) 84 return -1, nil, os.NewSyscallError("setnonblock", err) 85 } 86 return ns, sa, nil 87 }