Commit 3ba80d98 authored by Frederick Akalin's avatar Frederick Akalin Committed by Han-Wen Nienhuys

Add handleEINTR() function and use it for read/write/writev syscalls

EINTR is commonly encountered when running under a debugger, so this
change makes it possible to do so without hitting spurious
EINTR errors.
parent 6fd2fb13
......@@ -198,6 +198,25 @@ func (ms *Server) DebugData() string {
// What is a good number? Maybe the number of CPUs?
const _MAX_READERS = 2
// handleEINTR retries the given function until it doesn't return syscall.EINTR.
// This is similar to the HANDLE_EINTR() macro from Chromium ( see
// https://code.google.com/p/chromium/codesearch#chromium/src/base/posix/eintr_wrapper.h
// ) and the TEMP_FAILURE_RETRY() from glibc (see
// https://www.gnu.org/software/libc/manual/html_node/Interrupted-Primitives.html
// ).
//
// Don't use handleEINTR() with syscall.Close(); see
// https://code.google.com/p/chromium/issues/detail?id=269623 .
func handleEINTR(fn func() error) (err error) {
for {
err = fn()
if err != syscall.EINTR {
break
}
}
return
}
// Returns a new request, or error. In case exitIdle is given, returns
// nil, OK if we have too many readers already.
func (ms *Server) readRequest(exitIdle bool) (req *request, code Status) {
......@@ -212,7 +231,12 @@ func (ms *Server) readRequest(exitIdle bool) (req *request, code Status) {
ms.reqReaders++
ms.reqMu.Unlock()
n, err := syscall.Read(ms.mountFd, dest)
var n int
err := handleEINTR(func() error {
var err error
n, err = syscall.Read(ms.mountFd, dest)
return err
})
if err != nil {
code = ToStatus(err)
ms.reqPool.Put(req)
......
......@@ -6,7 +6,10 @@ import (
func (ms *Server) systemWrite(req *request, header []byte) Status {
if req.flatDataSize() == 0 {
_, err := syscall.Write(ms.mountFd, header)
err := handleEINTR(func() error {
_, err := syscall.Write(ms.mountFd, header)
return err
})
return ToStatus(err)
}
......
......@@ -7,7 +7,10 @@ import (
func (ms *Server) systemWrite(req *request, header []byte) Status {
if req.flatDataSize() == 0 {
_, err := syscall.Write(ms.mountFd, header)
err := handleEINTR(func() error {
_, err := syscall.Write(ms.mountFd, header)
return err
})
return ToStatus(err)
}
......
......@@ -9,11 +9,15 @@ import (
// TODO - move these into Go's syscall package.
func sys_writev(fd int, iovecs *syscall.Iovec, cnt int) (n int, errno int) {
func sys_writev(fd int, iovecs *syscall.Iovec, cnt int) (n int, err error) {
n1, _, e1 := syscall.Syscall(
syscall.SYS_WRITEV,
uintptr(fd), uintptr(unsafe.Pointer(iovecs)), uintptr(cnt))
return int(n1), int(e1)
n = int(n1)
if e1 != 0 {
err = syscall.Errno(e1)
}
return
}
func writev(fd int, packet [][]byte) (n int, err error) {
......@@ -30,9 +34,13 @@ func writev(fd int, packet [][]byte) (n int, err error) {
iovecs = append(iovecs, vec)
}
n, errno := sys_writev(fd, &iovecs[0], len(iovecs))
if errno != 0 {
err = os.NewSyscallError("writev", syscall.Errno(errno))
sysErr := handleEINTR(func() error {
var err error
n, err = sys_writev(fd, &iovecs[0], len(iovecs))
return err
})
if sysErr != nil {
err = os.NewSyscallError("writev", sysErr)
}
return n, err
}
......
......@@ -8,11 +8,15 @@ import (
// TODO - move these into Go's syscall package.
func sys_writev(fd int, iovecs *syscall.Iovec, cnt int) (n int, errno int) {
func sys_writev(fd int, iovecs *syscall.Iovec, cnt int) (n int, err error) {
n1, _, e1 := syscall.Syscall(
syscall.SYS_WRITEV,
uintptr(fd), uintptr(unsafe.Pointer(iovecs)), uintptr(cnt))
return int(n1), int(e1)
n = int(n1)
if e1 != 0 {
err = syscall.Errno(e1)
}
return n, err
}
func writev(fd int, packet [][]byte) (n int, err error) {
......@@ -29,9 +33,13 @@ func writev(fd int, packet [][]byte) (n int, err error) {
iovecs = append(iovecs, vec)
}
n, errno := sys_writev(fd, &iovecs[0], len(iovecs))
if errno != 0 {
err = os.NewSyscallError("writev", syscall.Errno(errno))
sysErr := handleEINTR(func() error {
var err error
n, err = sys_writev(fd, &iovecs[0], len(iovecs))
return err
})
if sysErr != nil {
err = os.NewSyscallError("writev", sysErr)
}
return n, err
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment