github.com/spotify/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/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 linux 9 10 package net 11 12 import "syscall" 13 14 // Wrapper around the socket system call that marks the returned file 15 // descriptor as nonblocking and close-on-exec. 16 func sysSocket(f, t, p int) (int, error) { 17 s, err := syscall.Socket(f, t|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, p) 18 // The SOCK_NONBLOCK and SOCK_CLOEXEC flags were introduced in 19 // Linux 2.6.27. If we get an EINVAL error, fall back to 20 // using socket without them. 21 if err == nil || err != syscall.EINVAL { 22 return s, err 23 } 24 25 // See ../syscall/exec_unix.go for description of ForkLock. 26 syscall.ForkLock.RLock() 27 s, err = syscall.Socket(f, t, p) 28 if err == nil { 29 syscall.CloseOnExec(s) 30 } 31 syscall.ForkLock.RUnlock() 32 if err != nil { 33 return -1, err 34 } 35 if err = syscall.SetNonblock(s, true); err != nil { 36 syscall.Close(s) 37 return -1, err 38 } 39 return s, nil 40 } 41 42 // Wrapper around the accept system call that marks the returned file 43 // descriptor as nonblocking and close-on-exec. 44 func accept(fd int) (int, syscall.Sockaddr, error) { 45 nfd, sa, err := syscall.Accept4(fd, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC) 46 // The accept4 system call was introduced in Linux 2.6.28. If 47 // we get an ENOSYS or EINVAL error, fall back to using accept. 48 if err == nil || (err != syscall.ENOSYS && err != syscall.EINVAL) { 49 return nfd, sa, err 50 } 51 52 // See ../syscall/exec_unix.go for description of ForkLock. 53 // It is probably okay to hold the lock across syscall.Accept 54 // because we have put fd.sysfd into non-blocking mode. 55 // However, a call to the File method will put it back into 56 // blocking mode. We can't take that risk, so no use of ForkLock here. 57 nfd, sa, err = syscall.Accept(fd) 58 if err == nil { 59 syscall.CloseOnExec(nfd) 60 } 61 if err != nil { 62 return -1, nil, err 63 } 64 if err = syscall.SetNonblock(nfd, true); err != nil { 65 syscall.Close(nfd) 66 return -1, nil, err 67 } 68 return nfd, sa, nil 69 }