The following pull request was submitted through Github. It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/3193
This e-mail was sent by the LXC bot, direct replies will not reach the author unless they happen to be subscribed to this list. === Description (from pull-request) === Signed-off-by: Christian Brauner <[email protected]>
From 8dd03bb4edceb03cb8951d2525099d988b3aac80 Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Wed, 19 Apr 2017 22:55:07 +0200 Subject: [PATCH 1/2] rsync: make our netcat handle EAGAIN In particular, some filesystems give this, and golang's io.Copy doesn't understand it and calls it an error. So let's instead just mask it and have io.Copy try again. Signed-off-by: Tycho Andersen <[email protected]> --- lxd/main_netcat.go | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/lxd/main_netcat.go b/lxd/main_netcat.go index f5be1b3..cc1bc83 100644 --- a/lxd/main_netcat.go +++ b/lxd/main_netcat.go @@ -6,6 +6,7 @@ import ( "net" "os" "sync" + "syscall" ) // Netcat is called with: @@ -34,7 +35,7 @@ func cmdNetcat(args []string) error { wg.Add(1) go func() { - io.Copy(os.Stdout, conn) + io.Copy(os.Stdout, hideAgainReader{conn}) conn.Close() wg.Done() }() @@ -47,3 +48,19 @@ func cmdNetcat(args []string) error { return nil } + +type retryOnEagainReader struct { + r io.Reader +} + +func (hr retryOnEagainReader) Read(p []byte) (int, error) { + n, err := hr.r.Read(p) + if err != nil { + // golang's io.Copy doesn't understand EAGAIN, so let's mask it + if errno, ok := err.(syscall.Errno); ok && errno == syscall.EAGAIN { + return n, nil + } + } + + return n, err +} From bfe10958850f6799da2919406c45c80a4e4f58b6 Mon Sep 17 00:00:00 2001 From: Christian Brauner <[email protected]> Date: Wed, 19 Apr 2017 23:06:39 +0200 Subject: [PATCH 2/2] rsync: handle EAGAIN properly Go's io.Copy() is not able to handle EAGAIN but Read() and Write() are. We need to keep retrying on EAGAIN. Closes #3168. Signed-off-by: Christian Brauner <[email protected]> --- lxd/main_netcat.go | 63 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/lxd/main_netcat.go b/lxd/main_netcat.go index cc1bc83..3591e4e 100644 --- a/lxd/main_netcat.go +++ b/lxd/main_netcat.go @@ -35,7 +35,7 @@ func cmdNetcat(args []string) error { wg.Add(1) go func() { - io.Copy(os.Stdout, hideAgainReader{conn}) + io.Copy(eagainWriter{os.Stdout}, eagainReader{conn}) conn.Close() wg.Done() }() @@ -49,18 +49,65 @@ func cmdNetcat(args []string) error { return nil } -type retryOnEagainReader struct { +type eagainReader struct { r io.Reader } -func (hr retryOnEagainReader) Read(p []byte) (int, error) { - n, err := hr.r.Read(p) - if err != nil { - // golang's io.Copy doesn't understand EAGAIN, so let's mask it - if errno, ok := err.(syscall.Errno); ok && errno == syscall.EAGAIN { - return n, nil +func (er eagainReader) Read(p []byte) (int, error) { + // keep retrying on EAGAIN + again: + n, err := er.r.Read(p) + if err == nil { + return n, nil + } + + var errno error + // EAGAIN errors can hide in os.PathError. My best explanation for this + // weirdness is that os.Stdout refers to /dev/stdout which is a path. + sysErr, ok := err.(*os.PathError) + if ok { + errno = sysErr.Err + } else { + tmpErrno, ok := err.(syscall.Errno) + if ok { + errno = tmpErrno + } + } + + if errno == syscall.EAGAIN { + goto again + } + + return n, err +} + +type eagainWriter struct { + w io.Writer +} + +func (ew eagainWriter) Write(p []byte) (int, error) { + // keep retrying on EAGAIN + again: + n, err := ew.w.Write(p) + if err == nil { + return n, nil + } + + var errno error + // EAGAIN errors can hide in os.PathError. My best explanation for this + // weirdness is that os.Stdout refers to /dev/stdout which is a path. + sysErr, ok := err.(*os.PathError) + if ok { + errno = sysErr.Err + } else { + tmpErrno, ok := err.(syscall.Errno) + if ok { + errno = tmpErrno } } + if errno == syscall.EAGAIN { + goto again + } return n, err }
_______________________________________________ lxc-devel mailing list [email protected] http://lists.linuxcontainers.org/listinfo/lxc-devel
