github.com/code-reading/golang@v0.0.0-20220303082512-ba5bc0e589a3/go/src/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 for platforms that provide a fast path for 6 // setting SetNonblock and CloseOnExec. 7 8 //go:build dragonfly || freebsd || illumos || linux || netbsd || openbsd 9 // +build dragonfly freebsd illumos linux netbsd openbsd 10 11 package net 12 13 import ( 14 "internal/poll" 15 "os" 16 "syscall" 17 ) 18 19 // Wrapper around the socket system call that marks the returned file 20 // descriptor as nonblocking and close-on-exec. 21 func sysSocket(family, sotype, proto int) (int, error) { 22 s, err := socketFunc(family, sotype|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, proto) 23 // On Linux the SOCK_NONBLOCK and SOCK_CLOEXEC flags were 24 // introduced in 2.6.27 kernel and on FreeBSD both flags were 25 // introduced in 10 kernel. If we get an EINVAL error on Linux 26 // or EPROTONOSUPPORT error on FreeBSD, fall back to using 27 // socket without them. 28 switch err { 29 case nil: 30 return s, nil 31 default: 32 return -1, os.NewSyscallError("socket", err) 33 case syscall.EPROTONOSUPPORT, syscall.EINVAL: 34 } 35 36 // See ../syscall/exec_unix.go for description of ForkLock. 37 syscall.ForkLock.RLock() 38 s, err = socketFunc(family, sotype, proto) 39 if err == nil { 40 syscall.CloseOnExec(s) 41 } 42 syscall.ForkLock.RUnlock() 43 if err != nil { 44 return -1, os.NewSyscallError("socket", err) 45 } 46 if err = syscall.SetNonblock(s, true); err != nil { 47 poll.CloseFunc(s) 48 return -1, os.NewSyscallError("setnonblock", err) 49 } 50 return s, nil 51 }