diff options
author | Andy Pan <i@andypan.me> | 2024-04-04 16:30:30 +0800 |
---|---|---|
committer | Gopher Robot <gobot@golang.org> | 2024-04-14 18:17:25 +0000 |
commit | 37f482223f331c4400797f72158fcf1eaa1793c4 (patch) | |
tree | 3a182c523095b09f38e281076acde5a7810d51b7 /src/net | |
parent | 16df5330e410cfc702d942eb0cf3707ccdfd2c1d (diff) | |
download | go-37f482223f331c4400797f72158fcf1eaa1793c4.tar.gz go-37f482223f331c4400797f72158fcf1eaa1793c4.zip |
net: separate the Solaris fast/slow path of setting SOCK_* from others
Along with the removal of the slow path from Linux and *BSD.
For #59359
Change-Id: I6c79594252e5e5f1c1c57c11e09458fcae3793d2
Reviewed-on: https://go-review.googlesource.com/c/go/+/577175
Reviewed-by: Damien Neil <dneil@google.com>
Auto-Submit: Ian Lance Taylor <iant@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Andy Pan <panjf2000@gmail.com>
Diffstat (limited to 'src/net')
-rw-r--r-- | src/net/sock_cloexec.go | 25 | ||||
-rw-r--r-- | src/net/sock_cloexec_solaris.go | 47 |
2 files changed, 48 insertions, 24 deletions
diff --git a/src/net/sock_cloexec.go b/src/net/sock_cloexec.go index 9eeb89746b..043522f0b6 100644 --- a/src/net/sock_cloexec.go +++ b/src/net/sock_cloexec.go @@ -5,12 +5,11 @@ // This file implements sysSocket for platforms that provide a fast path for // setting SetNonblock and CloseOnExec. -//go:build dragonfly || freebsd || linux || netbsd || openbsd || solaris +//go:build dragonfly || freebsd || linux || netbsd || openbsd package net import ( - "internal/poll" "os" "syscall" ) @@ -19,30 +18,8 @@ import ( // descriptor as nonblocking and close-on-exec. func sysSocket(family, sotype, proto int) (int, error) { s, err := socketFunc(family, sotype|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, proto) - // TODO: We can remove the fallback on Linux and *BSD, - // as currently supported versions all support accept4 - // with SOCK_CLOEXEC, but Solaris does not. See issue #59359. - switch err { - case nil: - return s, nil - default: - return -1, os.NewSyscallError("socket", err) - case syscall.EPROTONOSUPPORT, syscall.EINVAL: - } - - // See ../syscall/exec_unix.go for description of ForkLock. - syscall.ForkLock.RLock() - s, err = socketFunc(family, sotype, proto) - if err == nil { - syscall.CloseOnExec(s) - } - syscall.ForkLock.RUnlock() if err != nil { return -1, os.NewSyscallError("socket", err) } - if err = syscall.SetNonblock(s, true); err != nil { - poll.CloseFunc(s) - return -1, os.NewSyscallError("setnonblock", err) - } return s, nil } diff --git a/src/net/sock_cloexec_solaris.go b/src/net/sock_cloexec_solaris.go new file mode 100644 index 0000000000..04c3cdf254 --- /dev/null +++ b/src/net/sock_cloexec_solaris.go @@ -0,0 +1,47 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// This file implements sysSocket for platforms that provide a fast path for +// setting SetNonblock and CloseOnExec, but don't necessarily support it. +// Support for SOCK_* flags as part of the type parameter was added to Oracle +// Solaris in the 11.4 release. Thus, on releases prior to 11.4, we fall back +// to the combination of socket(3c) and fcntl(2). + +package net + +import ( + "internal/poll" + "internal/syscall/unix" + "os" + "syscall" +) + +// Wrapper around the socket system call that marks the returned file +// descriptor as nonblocking and close-on-exec. +func sysSocket(family, sotype, proto int) (int, error) { + // Perform a cheap test and try the fast path first. + if unix.SupportSockNonblockCloexec() { + s, err := socketFunc(family, sotype|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, proto) + if err != nil { + return -1, os.NewSyscallError("socket", err) + } + return s, nil + } + + // See ../syscall/exec_unix.go for description of ForkLock. + syscall.ForkLock.RLock() + s, err := socketFunc(family, sotype, proto) + if err == nil { + syscall.CloseOnExec(s) + } + syscall.ForkLock.RUnlock() + if err != nil { + return -1, os.NewSyscallError("socket", err) + } + if err = syscall.SetNonblock(s, true); err != nil { + poll.CloseFunc(s) + return -1, os.NewSyscallError("setnonblock", err) + } + return s, nil +} |