summaryrefslogtreecommitdiff
path: root/libgo/go/net/sock_cloexec.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/net/sock_cloexec.go')
-rw-r--r--libgo/go/net/sock_cloexec.go47
1 files changed, 28 insertions, 19 deletions
diff --git a/libgo/go/net/sock_cloexec.go b/libgo/go/net/sock_cloexec.go
index 3f22cd8f57..dec81855b6 100644
--- a/libgo/go/net/sock_cloexec.go
+++ b/libgo/go/net/sock_cloexec.go
@@ -5,7 +5,7 @@
// This file implements sysSocket and accept for platforms that
// provide a fast path for setting SetNonblock and CloseOnExec.
-// +build linux
+// +build freebsd linux
package net
@@ -13,18 +13,20 @@ import "syscall"
// Wrapper around the socket system call that marks the returned file
// descriptor as nonblocking and close-on-exec.
-func sysSocket(f, t, p int) (int, error) {
- s, err := syscall.Socket(f, t|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, p)
- // The SOCK_NONBLOCK and SOCK_CLOEXEC flags were introduced in
- // Linux 2.6.27. If we get an EINVAL error, fall back to
- // using socket without them.
- if err == nil || err != syscall.EINVAL {
+func sysSocket(family, sotype, proto int) (int, error) {
+ s, err := syscall.Socket(family, sotype|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, proto)
+ // On Linux the SOCK_NONBLOCK and SOCK_CLOEXEC flags were
+ // introduced in 2.6.27 kernel and on FreeBSD both flags were
+ // introduced in 10 kernel. If we get an EINVAL error on Linux
+ // or EPROTONOSUPPORT error on FreeBSD, fall back to using
+ // socket without them.
+ if err == nil || (err != syscall.EPROTONOSUPPORT && err != syscall.EINVAL) {
return s, err
}
// See ../syscall/exec_unix.go for description of ForkLock.
syscall.ForkLock.RLock()
- s, err = syscall.Socket(f, t, p)
+ s, err = syscall.Socket(family, sotype, proto)
if err == nil {
syscall.CloseOnExec(s)
}
@@ -41,12 +43,19 @@ func sysSocket(f, t, p int) (int, error) {
// Wrapper around the accept system call that marks the returned file
// descriptor as nonblocking and close-on-exec.
-func accept(fd int) (int, syscall.Sockaddr, error) {
- nfd, sa, err := syscall.Accept4(fd, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC)
- // The accept4 system call was introduced in Linux 2.6.28. If
- // we get an ENOSYS or EINVAL error, fall back to using accept.
- if err == nil || (err != syscall.ENOSYS && err != syscall.EINVAL) {
- return nfd, sa, err
+func accept(s int) (int, syscall.Sockaddr, error) {
+ ns, sa, err := syscall.Accept4(s, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC)
+ // On Linux the accept4 system call was introduced in 2.6.28
+ // kernel and on FreeBSD it was introduced in 10 kernel. If we
+ // get an ENOSYS error on both Linux and FreeBSD, or EINVAL
+ // error on Linux, fall back to using accept.
+ switch err {
+ default: // nil and errors other than the ones listed
+ return ns, sa, err
+ case syscall.ENOSYS: // syscall missing
+ case syscall.EINVAL: // some Linux use this instead of ENOSYS
+ case syscall.EACCES: // some Linux use this instead of ENOSYS
+ case syscall.EFAULT: // some Linux use this instead of ENOSYS
}
// See ../syscall/exec_unix.go for description of ForkLock.
@@ -54,16 +63,16 @@ func accept(fd int) (int, syscall.Sockaddr, error) {
// because we have put fd.sysfd into non-blocking mode.
// However, a call to the File method will put it back into
// blocking mode. We can't take that risk, so no use of ForkLock here.
- nfd, sa, err = syscall.Accept(fd)
+ ns, sa, err = syscall.Accept(s)
if err == nil {
- syscall.CloseOnExec(nfd)
+ syscall.CloseOnExec(ns)
}
if err != nil {
return -1, nil, err
}
- if err = syscall.SetNonblock(nfd, true); err != nil {
- syscall.Close(nfd)
+ if err = syscall.SetNonblock(ns, true); err != nil {
+ syscall.Close(ns)
return -1, nil, err
}
- return nfd, sa, nil
+ return ns, sa, nil
}