func (sc *selectCtx) Init() error { sc.rset.Zero() sc.wset.Zero() sc.fdmax = -1 // Create and configure the pipe-ends. b := make([]int, 2) err := syscall.Pipe(b) if err != nil { return err } sc.pfdr, sc.pfdw = b[0], b[1] syscall.CloseOnExec(sc.pfdr) syscall.CloseOnExec(sc.pfdw) err = syscall.SetNonblock(sc.pfdr, true) if err != nil { syscall.Close(sc.pfdr) syscall.Close(sc.pfdw) return err } err = syscall.SetNonblock(sc.pfdw, true) if err != nil { syscall.Close(sc.pfdr) syscall.Close(sc.pfdw) return err } // pfdr (read-end of pipe) is set (and remains set forever) on // rset. sc.rset.Set(sc.pfdr) sc.fdmax = sc.pfdr // allocate dummy selectCtx.{b,b1} buffers. sc.b = make([]byte, 1) sc.b1 = make([]byte, 128) return nil }
// OpenFile is the generalized open call; most users will use Open // or Create instead. It opens the named file with specified flag // (O_RDONLY etc.) and perm, (0666 etc.) if applicable. If successful, // methods on the returned File can be used for I/O. // If there is an error, it will be of type *PathError. func OpenFile(name string, flag int, perm FileMode) (file *File, err error) { chmod := false if !supportsCreateWithStickyBit && flag&O_CREATE != 0 && perm&ModeSticky != 0 { if _, err := Stat(name); IsNotExist(err) { chmod = true } } r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm)) if e != nil { return nil, &PathError{"open", name, e} } // open(2) itself won't handle the sticky bit on *BSD and Solaris if chmod { Chmod(name, perm) } // There's a race here with fork/exec, which we are // content to live with. See ../syscall/exec_unix.go. if !supportsCloseOnExec { syscall.CloseOnExec(r) } return NewFile(uintptr(r), name), nil }
// OpenFile is the generalized open call; most users will use Open // or Create instead. It opens the named file with specified flag // (O_RDONLY etc.) and perm, (0666 etc.) if applicable. If successful, // methods on the returned File can be used for I/O. // If there is an error, it will be of type *PathError. func OpenFile(name string, flag int, perm FileMode) (*File, error) { chmod := false if !supportsCreateWithStickyBit && flag&O_CREATE != 0 && perm&ModeSticky != 0 { if _, err := Stat(name); IsNotExist(err) { chmod = true } } retry: r, e := syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm)) if e != nil { // On OS X, sigaction(2) doesn't guarantee that SA_RESTART will cause // open(2) to be restarted for regular files. This is easy to reproduce on // fuse file systems (see http://golang.org/issue/11180). if e == syscall.EINTR { goto retry } return nil, &PathError{"open", name, e} } // open(2) itself won't handle the sticky bit on *BSD and Solaris if chmod { Chmod(name, perm) } // There's a race here with fork/exec, which we are // content to live with. See ../syscall/exec_unix.go. if !supportsCloseOnExec { syscall.CloseOnExec(r) } return NewFile(uintptr(r), name), nil }
// Wrapper around the accept system call that marks the returned file // descriptor as nonblocking and close-on-exec. func accept(s int) (int, syscall.Sockaddr, error) { ns, sa, err := syscall.Accept4(s, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC) // On Linux the accept4 system call was introduced in 2.6.28 // kernel and on FreeBSD it was introduced in 10 kernel. If we // get an ENOSYS error on both Linux and FreeBSD, or EINVAL // error on Linux, fall back to using accept. if err == nil || (err != syscall.ENOSYS && err != syscall.EINVAL) { return ns, sa, err } // See ../syscall/exec_unix.go for description of ForkLock. // It is probably okay to hold the lock across syscall.Accept // because we have put fd.sysfd into non-blocking mode. // However, a call to the File method will put it back into // blocking mode. We can't take that risk, so no use of ForkLock here. ns, sa, err = syscall.Accept(s) if err == nil { syscall.CloseOnExec(ns) } if err != nil { return -1, nil, err } if err = syscall.SetNonblock(ns, true); err != nil { syscall.Close(ns) return -1, nil, err } return ns, sa, nil }
// Wrapper around the accept system call that marks the returned file // descriptor as nonblocking and close-on-exec. func accept(fd int) (int, syscall.Sockaddr, error) { nfd, sa, err := syscall.Accept4(fd, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC) // The accept4 system call was introduced in Linux 2.6.28. If // we get an ENOSYS error, fall back to using accept. if err == nil || err != syscall.ENOSYS { return nfd, sa, err } // See ../syscall/exec_unix.go for description of ForkLock. // It is okay to hold the lock across syscall.Accept // because we have put fd.sysfd into non-blocking mode. syscall.ForkLock.RLock() nfd, sa, err = syscall.Accept(fd) if err == nil { syscall.CloseOnExec(nfd) } syscall.ForkLock.RUnlock() if err != nil { return -1, nil, err } if err = syscall.SetNonblock(nfd, true); err != nil { syscall.Close(nfd) return -1, nil, err } return nfd, sa, nil }
// Pipe returns a connected pair of Files; reads from r return bytes written to w. // It returns the files and an Error, if any. func Pipe() (r *File, w *File, err Error) { var p [2]int // See ../syscall/exec.go for description of lock. syscall.ForkLock.RLock() e := syscall.Pipe(&p) if e != 0 { syscall.ForkLock.RUnlock() return nil, nil, NewSyscallError("pipe", e) } syscall.CloseOnExec(p[0]) syscall.CloseOnExec(p[1]) syscall.ForkLock.RUnlock() return NewFile(p[0], "|0"), NewFile(p[1], "|1"), nil }
// Wrapper around the socket system call that marks the returned file // descriptor as nonblocking and close-on-exec. func sysSocket(f, t, p int) (int, error) { s, err := syscall.Socket(f, t|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, p) // The SOCK_NONBLOCK and SOCK_CLOEXEC flags were introduced in // Linux 2.6.27. If we get an EINVAL error, fall back to // using socket without them. if err == nil || err != syscall.EINVAL { return s, err } // See ../syscall/exec_unix.go for description of ForkLock. syscall.ForkLock.RLock() s, err = syscall.Socket(f, t, p) if err == nil { syscall.CloseOnExec(s) } syscall.ForkLock.RUnlock() if err != nil { return -1, err } if err = syscall.SetNonblock(s, true); err != nil { syscall.Close(s) return -1, err } return s, nil }
func Files(unsetEnv bool) []*os.File { if unsetEnv { // there is no way to unset env in golang os package for now // https://code.google.com/p/go/issues/detail?id=6423 defer os.Setenv("LISTEN_PID", "") defer os.Setenv("LISTEN_FDS", "") } pid, err := strconv.Atoi(os.Getenv("LISTEN_PID")) if err != nil || pid != os.Getpid() { return nil } nfds, err := strconv.Atoi(os.Getenv("LISTEN_FDS")) if err != nil || nfds == 0 { return nil } var files []*os.File for fd := listenFdsStart; fd < listenFdsStart+nfds; fd++ { syscall.CloseOnExec(fd) files = append(files, os.NewFile(uintptr(fd), "LISTEN_FD_"+strconv.Itoa(fd))) } return files }
// Wrapper around the accept system call that marks the returned file // descriptor as nonblocking and close-on-exec. func accept(fd int) (int, syscall.Sockaddr, error) { nfd, sa, err := syscall.Accept4(fd, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC) // The accept4 system call was introduced in Linux 2.6.28. If // we get an ENOSYS error, fall back to using accept. if err == nil || err != syscall.ENOSYS { return nfd, sa, err } // See ../syscall/exec_unix.go for description of ForkLock. // It is probably okay to hold the lock across syscall.Accept // because we have put fd.sysfd into non-blocking mode. // However, a call to the File method will put it back into // blocking mode. We can't take that risk, so no use of ForkLock here. nfd, sa, err = syscall.Accept(fd) if err == nil { syscall.CloseOnExec(nfd) } if err != nil { return -1, nil, err } if err = syscall.SetNonblock(nfd, true); err != nil { syscall.Close(nfd) return -1, nil, err } return nfd, sa, nil }
// Wrapper around the accept system call that marks the returned file // descriptor as nonblocking and close-on-exec. func accept(s int) (int, syscall.Sockaddr, error) { ns, sa, err := accept4Func(s, syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC) // On Linux the accept4 system call was introduced in 2.6.28 // kernel and on FreeBSD it was introduced in 10 kernel. If we // get an ENOSYS error on both Linux and FreeBSD, or EINVAL // error on Linux, fall back to using accept. switch err { default: // nil and errors other than the ones listed return ns, sa, err case syscall.ENOSYS: // syscall missing case syscall.EINVAL: // some Linux use this instead of ENOSYS case syscall.EACCES: // some Linux use this instead of ENOSYS case syscall.EFAULT: // some Linux use this instead of ENOSYS } // See ../syscall/exec_unix.go for description of ForkLock. // It is probably okay to hold the lock across syscall.Accept // because we have put fd.sysfd into non-blocking mode. // However, a call to the File method will put it back into // blocking mode. We can't take that risk, so no use of ForkLock here. ns, sa, err = acceptFunc(s) if err == nil { syscall.CloseOnExec(ns) } if err != nil { return -1, nil, err } if err = syscall.SetNonblock(ns, true); err != nil { closeFunc(ns) return -1, nil, err } return ns, sa, nil }
// 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) { // 创建socket套接字 s, err := socketFunc(family, sotype|syscall.SOCK_NONBLOCK|syscall.SOCK_CLOEXEC, proto) // On Linux the SOCK_NONBLOCK and SOCK_CLOEXEC flags were // introduced in 2.6.27 kernel and on FreeBSD both flags were // introduced in 10 kernel. If we get an EINVAL error on Linux // or EPROTONOSUPPORT error on FreeBSD, fall back to using // socket without them. 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 { closeFunc(s) return -1, os.NewSyscallError("setnonblock", err) } return s, nil }
func extractFds(oob []byte) (fds []int) { // Grab forklock to make sure no forks accidentally inherit the new // fds before they are made CLOEXEC // There is a slight race condition between ReadMsgUnix returns and // when we grap the lock, so this is not perfect. Unfortunately // There is no way to pass MSG_CMSG_CLOEXEC to recvmsg() nor any // way to implement non-blocking i/o in go, so this is hard to fix. syscall.ForkLock.Lock() defer syscall.ForkLock.Unlock() scms, err := syscall.ParseSocketControlMessage(oob) if err != nil { return } for _, scm := range scms { gotFds, err := syscall.ParseUnixRights(&scm) if err != nil { continue } fds = append(fds, gotFds...) for _, fd := range fds { syscall.CloseOnExec(fd) } } return }
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.Error) { if fd == nil || fd.file == nil { return nil, os.EINVAL } // See ../syscall/exec.go for description of ForkLock. // It is okay to hold the lock across syscall.Accept // because we have put fd.fd into non-blocking mode. syscall.ForkLock.RLock() var s, e int var sa syscall.Sockaddr for { s, sa, e = syscall.Accept(fd.fd) if e != syscall.EAGAIN { break } syscall.ForkLock.RUnlock() pollserver.WaitRead(fd) syscall.ForkLock.RLock() } if e != 0 { syscall.ForkLock.RUnlock() return nil, &OpError{"accept", fd.net, fd.laddr, os.Errno(e)} } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() if nfd, err = newFD(s, fd.family, fd.proto, fd.net, fd.laddr, toAddr(sa)); err != nil { syscall.Close(s) return nil, err } return nfd, nil }
// NOTE: Taken from the Go source: src/net/sock_cloexec.go // 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) { s, err := syscall.Socket(family, sotype|syscall.SOCK_CLOEXEC, proto) // On Linux the SOCK_NONBLOCK and SOCK_CLOEXEC flags were // introduced in 2.6.27 kernel and on FreeBSD both flags were // introduced in 10 kernel. If we get an EINVAL error on Linux // or EPROTONOSUPPORT error on FreeBSD, fall back to using // socket without them. if err == nil || (err != syscall.EPROTONOSUPPORT && err != syscall.EINVAL) { return s, err } // See ../syscall/exec_unix.go for description of ForkLock. syscall.ForkLock.RLock() s, err = syscall.Socket(family, sotype, proto) if err == nil { syscall.CloseOnExec(s) } syscall.ForkLock.RUnlock() if err != nil { return -1, err } if err = syscall.SetNonblock(s, true); err != nil { syscall.Close(s) return -1, err } return s, nil }
// Pipe returns a connected pair of Files; reads from r return bytes written to w. // It returns the files and an error, if any. func Pipe() (r *File, w *File, err error) { var p [2]syscall.Handle // See ../syscall/exec.go for description of lock. syscall.ForkLock.RLock() e := syscall.Pipe(p[0:]) if e != nil { syscall.ForkLock.RUnlock() return nil, nil, NewSyscallError("pipe", e) } syscall.CloseOnExec(p[0]) syscall.CloseOnExec(p[1]) syscall.ForkLock.RUnlock() return NewFile(uintptr(p[0]), "|0"), NewFile(uintptr(p[1]), "|1"), nil }
// Generic socket creation. func socket(net string, f, t, p int, ipv6only bool, ulsa, ursa syscall.Sockaddr, deadline time.Time, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) { // See ../syscall/exec_unix.go for description of ForkLock. syscall.ForkLock.RLock() s, err := syscall.Socket(f, t, p) if err != nil { syscall.ForkLock.RUnlock() return nil, err } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() if err = setDefaultSockopts(s, f, t, ipv6only); err != nil { closesocket(s) return nil, err } if ulsa != nil { // We provide a socket that listens to a wildcard // address with reusable UDP port when the given ulsa // is an appropriate UDP multicast address prefix. // This makes it possible for a single UDP listener // to join multiple different group addresses, for // multiple UDP listeners that listen on the same UDP // port to join the same group address. if ulsa, err = listenerSockaddr(s, f, ulsa, toAddr); err != nil { closesocket(s) return nil, err } if err = syscall.Bind(s, ulsa); err != nil { closesocket(s) return nil, err } } if fd, err = newFD(s, f, t, net); err != nil { closesocket(s) return nil, err } if ursa != nil { if !deadline.IsZero() { fd.wdeadline = deadline.UnixNano() } if err = fd.connect(ursa); err != nil { closesocket(s) fd.Close() return nil, err } fd.isConnected = true fd.wdeadline = 0 } lsa, _ := syscall.Getsockname(s) laddr := toAddr(lsa) rsa, _ := syscall.Getpeername(s) raddr := toAddr(rsa) fd.setAddr(laddr, raddr) return fd, nil }
func NewPoll() (p *pollster, err error) { p = new(pollster) if p.kq, err = syscall.Kqueue(); err != nil { return nil, os.NewSyscallError("kqueue", err) } syscall.CloseOnExec(p.kq) return p, nil }
// Generic socket creation. func socket(net string, f, t, p int, ipv6only bool, la, ra syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err error) { // See ../syscall/exec.go for description of ForkLock. syscall.ForkLock.RLock() s, err := syscall.Socket(f, t, p) if err != nil { syscall.ForkLock.RUnlock() return nil, err } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() err = setDefaultSockopts(s, f, t, ipv6only) if err != nil { closesocket(s) return nil, err } var bla syscall.Sockaddr if la != nil { bla, err = listenerSockaddr(s, f, la, toAddr) if err != nil { closesocket(s) return nil, err } err = syscall.Bind(s, bla) if err != nil { closesocket(s) return nil, err } } if fd, err = newFD(s, f, t, net); err != nil { closesocket(s) return nil, err } if ra != nil { if err = fd.connect(ra); err != nil { closesocket(s) fd.Close() return nil, err } fd.isConnected = true } sa, _ := syscall.Getsockname(s) var laddr Addr if la != nil && bla != la { laddr = toAddr(la) } else { laddr = toAddr(sa) } sa, _ = syscall.Getpeername(s) raddr := toAddr(sa) fd.setAddr(laddr, raddr) return fd, nil }
func newFileFD(f *os.File) (*netFD, error) { syscall.ForkLock.RLock() fd, err := syscall.Dup(int(f.Fd())) if err != nil { syscall.ForkLock.RUnlock() return nil, os.NewSyscallError("dup", err) } syscall.CloseOnExec(fd) syscall.ForkLock.RUnlock() sotype, err := syscall.GetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TYPE) if err != nil { closesocket(fd) return nil, os.NewSyscallError("getsockopt", err) } family := syscall.AF_UNSPEC toAddr := sockaddrToTCP sa, _ := syscall.Getsockname(fd) switch sa.(type) { default: closesocket(fd) return nil, syscall.EINVAL case *syscall.SockaddrInet4: family = syscall.AF_INET if sotype == syscall.SOCK_DGRAM { toAddr = sockaddrToUDP } else if sotype == syscall.SOCK_RAW { toAddr = sockaddrToIP } case *syscall.SockaddrInet6: family = syscall.AF_INET6 if sotype == syscall.SOCK_DGRAM { toAddr = sockaddrToUDP } else if sotype == syscall.SOCK_RAW { toAddr = sockaddrToIP } case *syscall.SockaddrUnix: family = syscall.AF_UNIX toAddr = sockaddrToUnix if sotype == syscall.SOCK_DGRAM { toAddr = sockaddrToUnixgram } else if sotype == syscall.SOCK_SEQPACKET { toAddr = sockaddrToUnixpacket } } laddr := toAddr(sa) sa, _ = syscall.Getpeername(fd) raddr := toAddr(sa) netfd, err := newFD(fd, family, sotype, laddr.Network()) if err != nil { closesocket(fd) return nil, err } netfd.setAddr(laddr, raddr) return netfd, nil }
func newpollster() (p *pollster, err error) { p = new(pollster) if p.kq, err = syscall.Kqueue(); err != nil { return nil, os.NewSyscallError("kqueue", err) } syscall.CloseOnExec(p.kq) p.events = p.eventbuf[0:0] return p, nil }
// Opens an available pseudo-terminal and returns Terminal controllers for the master and // slave. Also returns an Error, if any. func OpenPty(attr *Attributes, size *WindowSize) (*Terminal, *Terminal, os.Error) { cattr := makeCAttributes(attr) csize := makeCWindowSize(size) // see Go sources @src/pkg/syscall/exec.go for ForkLock info syscall.ForkLock.RLock() result := C.goterm_openpty(&cattr, &csize) if result.result < 0 { syscall.ForkLock.RUnlock() return nil, nil, os.NewError("Unable to open pty.") } syscall.CloseOnExec(int(result.master)) syscall.CloseOnExec(int(result.slave)) syscall.ForkLock.RUnlock() master := &Terminal{os.NewFile(int(result.master), C.GoString(C.ttyname(result.master)))} slave := &Terminal{os.NewFile(int(result.slave), C.GoString(C.ttyname(result.slave)))} return master, slave, nil }
// dupCloseOnExecUnixOld is the traditional way to dup an fd and // set its O_CLOEXEC bit, using two system calls. func dupCloseOnExecOld(fd int) (newfd int, err error) { syscall.ForkLock.RLock() defer syscall.ForkLock.RUnlock() newfd, err = syscall.Dup(fd) if err != nil { return -1, os.NewSyscallError("dup", err) } syscall.CloseOnExec(newfd) return }
func sysSocket(f, t, p int) (syscall.Handle, error) { // See ../syscall/exec_unix.go for description of ForkLock. syscall.ForkLock.RLock() s, err := syscall.Socket(f, t, p) if err == nil { syscall.CloseOnExec(s) } syscall.ForkLock.RUnlock() return s, err }
func sysSocket(family, sotype, proto int) (syscall.Handle, error) { // 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() return s, err }
// Listen returns TCP listener with SO_REUSEPORT option set. // // Only tcp4 network is supported. // // ErrNoReusePort error is returned if the system doesn't support SO_REUSEPORT. func Listen(network, addr string) (l net.Listener, err error) { var ( soType, fd int file *os.File sockaddr syscall.Sockaddr ) if sockaddr, soType, err = getSockaddr(network, addr); err != nil { return nil, err } syscall.ForkLock.RLock() fd, err = syscall.Socket(soType, syscall.SOCK_STREAM, syscall.IPPROTO_TCP) if err == nil { syscall.CloseOnExec(fd) } syscall.ForkLock.RUnlock() if err != nil { return nil, err } if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil { syscall.Close(fd) return nil, err } if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, soReusePort, 1); err != nil { syscall.Close(fd) return nil, &ErrNoReusePort{err} } if err = syscall.Bind(fd, sockaddr); err != nil { syscall.Close(fd) return nil, err } if err = syscall.Listen(fd, syscall.SOMAXCONN); err != nil { syscall.Close(fd) return nil, err } name := fmt.Sprintf("reuseport.%d.%s.%s", os.Getpid(), network, addr) file = os.NewFile(uintptr(fd), name) if l, err = net.FileListener(file); err != nil { file.Close() return nil, err } if err = file.Close(); err != nil { l.Close() return nil, err } return l, err }
// Generic socket creation. func socket(net string, f, p, t int, la, ra syscall.Sockaddr, toAddr func(syscall.Sockaddr) Addr) (fd *netFD, err os.Error) { // See ../syscall/exec.go for description of ForkLock. syscall.ForkLock.RLock() s, e := syscall.Socket(f, p, t) if e != 0 { syscall.ForkLock.RUnlock() return nil, os.Errno(e) } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() // Allow reuse of recently-used addresses. syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1) // Allow broadcast. syscall.SetsockoptInt(s, syscall.SOL_SOCKET, syscall.SO_BROADCAST, 1) if f == syscall.AF_INET6 { // using ip, tcp, udp, etc. // allow both protocols even if the OS default is otherwise. syscall.SetsockoptInt(s, syscall.IPPROTO_IPV6, syscall.IPV6_V6ONLY, 0) } if la != nil { e = syscall.Bind(s, la) if e != 0 { closesocket(s) return nil, os.Errno(e) } } if ra != nil { e = syscall.Connect(s, ra) for e == syscall.EINTR { e = syscall.Connect(s, ra) } if e != 0 { closesocket(s) return nil, os.Errno(e) } } sa, _ := syscall.Getsockname(s) laddr := toAddr(sa) sa, _ = syscall.Getpeername(s) raddr := toAddr(sa) fd, err = newFD(s, f, p, net, laddr, raddr) if err != nil { closesocket(s) return nil, err } return fd, nil }
// Pipe returns a connected pair of Files; reads from // r return bytes written to w. It returns the files and an error, if any. // Optionally, r or w might be set to non-blocking mode using the appropriate // flags. To obtain a blocking pipe just pass 0 as the flag. func Pipe(flag PipeFlag) (r *os.File, w *os.File, err error) { var p [2]int syscall.ForkLock.RLock() if err := syscall.Pipe(p[:]); err != nil { syscall.ForkLock.RUnlock() return nil, nil, os.NewSyscallError("pipe", err) } syscall.CloseOnExec(p[0]) syscall.CloseOnExec(p[1]) if flag&ReadNonBlock != 0 { syscall.SetNonblock(p[0], true) } if flag&WriteNonBlock != 0 { syscall.SetNonblock(p[1], true) } syscall.ForkLock.RUnlock() return os.NewFile(uintptr(p[0]), "|0"), os.NewFile(uintptr(p[1]), "|1"), nil }
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err os.Error) { if fd == nil || fd.sysfd == syscall.InvalidHandle { return nil, os.EINVAL } fd.incref() defer fd.decref() // Get new socket. // See ../syscall/exec.go for description of ForkLock. syscall.ForkLock.RLock() s, e := syscall.Socket(fd.family, fd.proto, 0) if e != 0 { syscall.ForkLock.RUnlock() return nil, os.Errno(e) } syscall.CloseOnExec(s) syscall.ForkLock.RUnlock() // Associate our new socket with IOCP. onceStartServer.Do(startServer) if _, e = syscall.CreateIoCompletionPort(s, resultsrv.iocp, 0, 0); e != 0 { return nil, &OpError{"CreateIoCompletionPort", fd.net, fd.laddr, os.Errno(e)} } // Submit accept request. var o acceptOp o.Init(fd, 'r') o.newsock = s _, err = iosrv.ExecIO(&o, 0) if err != nil { closesocket(s) return nil, err } // Inherit properties of the listening socket. e = syscall.Setsockopt(s, syscall.SOL_SOCKET, syscall.SO_UPDATE_ACCEPT_CONTEXT, (*byte)(unsafe.Pointer(&fd.sysfd)), int32(unsafe.Sizeof(fd.sysfd))) if e != 0 { closesocket(s) return nil, err } // Get local and peer addr out of AcceptEx buffer. var lrsa, rrsa *syscall.RawSockaddrAny var llen, rlen int32 l := uint32(unsafe.Sizeof(*lrsa)) syscall.GetAcceptExSockaddrs((*byte)(unsafe.Pointer(&o.attrs[0])), 0, l, l, &lrsa, &llen, &rrsa, &rlen) lsa, _ := lrsa.Sockaddr() rsa, _ := rrsa.Sockaddr() nfd = allocFD(s, fd.family, fd.proto, fd.net) nfd.setAddr(toAddr(lsa), toAddr(rsa)) return nfd, nil }
func (vm *Vm) NewVcpu(id uint) (*Vcpu, error) { // Create a new Vcpu. vcpufd, _, e := syscall.Syscall( syscall.SYS_IOCTL, uintptr(vm.fd), uintptr(C.IoctlCreateVcpu), uintptr(id)) if e != 0 { return nil, e } // Make sure this disappears on exec. // This is a race condition here, but realistically // we are not going to be restarting at this point. syscall.CloseOnExec(int(vcpufd)) // Map our shared data. mmap, err := syscall.Mmap( int(vcpufd), 0, vm.mmap_size, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_SHARED) if err != nil { syscall.Close(int(vcpufd)) return nil, err } kvm_run := (*C.struct_kvm_run)(unsafe.Pointer(&mmap[0])) // Add our Vcpu. vcpu := &Vcpu{ Id: id, fd: int(vcpufd), mmap: mmap, kvm: kvm_run, msrs: vm.msrs, cpuid: vm.cpuid, } vm.vcpus = append(vm.vcpus, vcpu) // Set our default cpuid. // (This may be overriden later). err = vcpu.SetCpuid(vm.cpuid) if err != nil { vcpu.Dispose() return nil, err } // Return our VCPU object. return vcpu, vcpu.initRunInfo() }
func setCloseOnExec(name string) { if fileInfos, _ := ioutil.ReadDir("/proc/self/fd"); fileInfos != nil { for _, i := range fileInfos { link, _ := os.Readlink(filepath.Join("/proc/self/fd", i.Name())) if link == name { fd, err := strconv.Atoi(i.Name()) if err == nil { syscall.CloseOnExec(fd) } } } } }