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