Commit 1d086e39 authored by Mikio Hara's avatar Mikio Hara

net: enable fast socket creation with close-on-exec flag on freebsd

Also makes variable names explicit.

Fixes #7186.

LGTM=iant
R=golang-codereviews, gobot, iant, bradfitz
CC=golang-codereviews
https://golang.org/cl/69100043
parent a918c2c6
......@@ -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,14 @@ 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.
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.
if err == nil || (err != syscall.ENOSYS && err != syscall.EINVAL) {
return nfd, sa, err
return ns, sa, err
}
// See ../syscall/exec_unix.go for description of ForkLock.
......@@ -54,16 +58,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
}
......@@ -5,7 +5,7 @@
// This file implements sysSocket and accept for platforms that do not
// provide a fast path for setting SetNonblock and CloseOnExec.
// +build darwin dragonfly freebsd nacl netbsd openbsd solaris
// +build darwin dragonfly nacl netbsd openbsd solaris
package net
......@@ -13,10 +13,10 @@ 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) {
func sysSocket(family, sotype, proto int) (int, error) {
// 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)
}
......@@ -33,22 +33,22 @@ 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) {
func accept(s int) (int, syscall.Sockaddr, error) {
// See ../syscall/exec_unix.go for description of ForkLock.
// It is probably okay to hold the lock across syscall.Accept
// 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
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment