1// Copyright 2024 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 for platforms that provide a fast path for
6// setting SetNonblock and CloseOnExec, but don't necessarily support it.
7// Support for SOCK_* flags as part of the type parameter was added to Oracle
8// Solaris in the 11.4 release. Thus, on releases prior to 11.4, we fall back
9// to the combination of socket(3c) and fcntl(2).
10
11package net
12
13import (
14	"internal/poll"
15	"internal/syscall/unix"
16	"os"
17	"syscall"
18)
19
20// Wrapper around the socket system call that marks the returned file
21// descriptor as nonblocking and close-on-exec.
22func sysSocket(family, sotype, proto int) (int, error) {
23	// Perform a cheap test and try the fast path first.
24	if unix.SupportSockNonblockCloexec() {
25		s, err := socketFunc(family, sotype|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, proto)
26		if err != nil {
27			return -1, os.NewSyscallError("socket", err)
28		}
29		return s, nil
30	}
31
32	// See ../syscall/exec_unix.go for description of ForkLock.
33	syscall.ForkLock.RLock()
34	s, err := socketFunc(family, sotype, proto)
35	if err == nil {
36		syscall.CloseOnExec(s)
37	}
38	syscall.ForkLock.RUnlock()
39	if err != nil {
40		return -1, os.NewSyscallError("socket", err)
41	}
42	if err = syscall.SetNonblock(s, true); err != nil {
43		poll.CloseFunc(s)
44		return -1, os.NewSyscallError("setnonblock", err)
45	}
46	return s, nil
47}
48