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 do not
      6 // provide a fast path for setting SetNonblock and CloseOnExec.
      7 
      8 // +build darwin dragonfly nacl netbsd openbsd solaris
      9 
     10 package net
     11 
     12 import (
     13 	"os"
     14 	"syscall"
     15 )
     16 
     17 // Wrapper around the socket system call that marks the returned file
     18 // descriptor as nonblocking and close-on-exec.
     19 func sysSocket(family, sotype, proto int) (int, error) {
     20 	// See ../syscall/exec_unix.go for description of ForkLock.
     21 	syscall.ForkLock.RLock()
     22 	s, err := socketFunc(family, sotype, proto)
     23 	if err == nil {
     24 		syscall.CloseOnExec(s)
     25 	}
     26 	syscall.ForkLock.RUnlock()
     27 	if err != nil {
     28 		return -1, os.NewSyscallError("socket", err)
     29 	}
     30 	if err = syscall.SetNonblock(s, true); err != nil {
     31 		closeFunc(s)
     32 		return -1, os.NewSyscallError("setnonblock", err)
     33 	}
     34 	return s, nil
     35 }
     36 
     37 // Wrapper around the accept system call that marks the returned file
     38 // descriptor as nonblocking and close-on-exec.
     39 func accept(s int) (int, syscall.Sockaddr, error) {
     40 	// See ../syscall/exec_unix.go for description of ForkLock.
     41 	// It is probably okay to hold the lock across syscall.Accept
     42 	// because we have put fd.sysfd into non-blocking mode.
     43 	// However, a call to the File method will put it back into
     44 	// blocking mode. We can't take that risk, so no use of ForkLock here.
     45 	ns, sa, err := acceptFunc(s)
     46 	if err == nil {
     47 		syscall.CloseOnExec(ns)
     48 	}
     49 	if err != nil {
     50 		return -1, nil, os.NewSyscallError("accept", err)
     51 	}
     52 	if err = syscall.SetNonblock(ns, true); err != nil {
     53 		closeFunc(ns)
     54 		return -1, nil, os.NewSyscallError("setnonblock", err)
     55 	}
     56 	return ns, sa, nil
     57 }
     58