The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/6867

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) ===
- Adds ability to switch `WebsocketExecMirror` from using custom `poll` to using standard `read`.
- Closes PTYs earlier to prevent `WebsocketExecMirror` from blocking on reading of file handle.

From 0d76248959f4b96ecbff4e8740d616455cb6a061 Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 11 Feb 2020 12:13:32 +0000
Subject: [PATCH 1/3] shared/network: Don't log contents of file handle in
 WebsocketRecvStream

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 shared/network.go | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/shared/network.go b/shared/network.go
index 71e5f09551..3a49052850 100644
--- a/shared/network.go
+++ b/shared/network.go
@@ -211,7 +211,7 @@ func WebsocketRecvStream(w io.Writer, conn *websocket.Conn) 
chan bool {
                        }
 
                        if err != nil {
-                               logger.Debugf("Got error getting next reader 
%s, %s", err, w)
+                               logger.Debugf("Got error getting next reader 
%s", err)
                                break
                        }
 

From 5106f95ceb32b8a0603326906279f30e2d66deea Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 11 Feb 2020 12:13:57 +0000
Subject: [PATCH 2/3] shared/netutils/network/linux: Adds ability to switch
 WebsocketExecMirror to use ReaderToChannel

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 shared/netutils/network_linux.go | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/shared/netutils/network_linux.go b/shared/netutils/network_linux.go
index cbea0423b3..93f0846768 100644
--- a/shared/netutils/network_linux.go
+++ b/shared/netutils/network_linux.go
@@ -171,14 +171,22 @@ func NetnsGetifaddrs(initPID int32) 
(map[string]api.InstanceStateNetwork, error)
        return networks, nil
 }
 
-func WebsocketExecMirror(conn *websocket.Conn, w io.WriteCloser, r 
io.ReadCloser, exited chan bool, fd int) (chan bool, chan bool) {
+// WebsocketExecMirror if supplied with pollFd then it uses polling on that 
descriptor.
+func WebsocketExecMirror(conn *websocket.Conn, w io.WriteCloser, r 
io.ReadCloser, exited chan bool, pollFd int) (chan bool, chan bool) {
        readDone := make(chan bool, 1)
        writeDone := make(chan bool, 1)
 
        go shared.DefaultWriter(conn, w, writeDone)
 
        go func(conn *websocket.Conn, r io.ReadCloser) {
-               in := shared.ExecReaderToChannel(r, -1, exited, fd)
+               var in <-chan []byte
+               if pollFd > 0 {
+                       in = shared.ExecReaderToChannel(r, -1, exited, pollFd)
+
+               } else {
+                       in = shared.ReaderToChannel(r, -1)
+               }
+
                for {
                        buf, ok := <-in
                        if !ok {

From 28c0f927e295e3bb5873ef780b478a86338c8fce Mon Sep 17 00:00:00 2001
From: Thomas Parrott <thomas.parr...@canonical.com>
Date: Tue, 11 Feb 2020 12:14:41 +0000
Subject: [PATCH 3/3] lxd/container/exec: Switch WebsocketMirror to use
 standard read mechanism for VMs

Closes PTY earlier so it doesn't block the mirror function.

Signed-off-by: Thomas Parrott <thomas.parr...@canonical.com>
---
 lxd-agent/exec.go     | 15 ++++++++-------
 lxd/container_exec.go | 22 ++++++++++++++--------
 2 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/lxd-agent/exec.go b/lxd-agent/exec.go
index 1feddb8325..7bbc84643a 100644
--- a/lxd-agent/exec.go
+++ b/lxd-agent/exec.go
@@ -349,8 +349,9 @@ func (s *execWs) Do(op *operations.Operation) error {
                        conn := s.conns[0]
                        s.connsLock.Unlock()
 
-                       logger.Info("Started mirroring websocket")
-                       readDone, writeDone := 
netutils.WebsocketExecMirror(conn, ptys[0], ptys[0], attachedChildIsDead, 
int(ptys[0].Fd()))
+                       pollFD := int(ptys[0].Fd())
+                       logger.Infof("Started mirroring websocket with FD %v", 
pollFD)
+                       readDone, writeDone := 
netutils.WebsocketExecMirror(conn, ptys[0], ptys[0], attachedChildIsDead, 
pollFD)
 
                        <-readDone
                        <-writeDone
@@ -388,6 +389,11 @@ func (s *execWs) Do(op *operations.Operation) error {
                        tty.Close()
                }
 
+               // Ensure PTYs are closed before websocket to end wgEOF.Wait().
+               for _, pty := range ptys {
+                       pty.Close()
+               }
+
                s.connsLock.Lock()
                conn := s.conns[-1]
                s.connsLock.Unlock()
@@ -401,13 +407,8 @@ func (s *execWs) Do(op *operations.Operation) error {
                }
 
                attachedChildIsDead <- true
-
                wgEOF.Wait()
 
-               for _, pty := range ptys {
-                       pty.Close()
-               }
-
                metadata := shared.Jmap{"return": cmdResult}
                err = op.UpdateMetadata(metadata)
                if err != nil {
diff --git a/lxd/container_exec.go b/lxd/container_exec.go
index 2302ee54b3..0853b8b923 100644
--- a/lxd/container_exec.go
+++ b/lxd/container_exec.go
@@ -240,10 +240,16 @@ func (s *execWs) Do(op *operations.Operation) error {
                        conn := s.conns[0]
                        s.connsLock.Unlock()
 
-                       logger.Debugf("Started mirroring websocket")
-                       defer logger.Debugf("Finished mirroring websocket")
-                       readDone, writeDone := 
netutils.WebsocketExecMirror(conn, ptys[0], ptys[0], attachedChildIsDead, 
int(ptys[0].Fd()))
+                       pollFD := 0
+
+                       // Use the polling mechanism for websocket mirror if 
local container, otherwise use reads.
+                       if s.instance.Type() == instancetype.Container {
+                               pollFD = int(ptys[0].Fd())
+                       }
 
+                       logger.Debugf("Started mirroring websocket with FD %v", 
pollFD)
+                       defer logger.Debugf("Finished mirroring websocket")
+                       readDone, writeDone := 
netutils.WebsocketExecMirror(conn, ptys[0], ptys[0], attachedChildIsDead, 
pollFD)
                        <-readDone
                        <-writeDone
                        conn.Close()
@@ -279,6 +285,11 @@ func (s *execWs) Do(op *operations.Operation) error {
                        tty.Close()
                }
 
+               // Ensure PTYs are closed before websocket to end wgEOF.Wait().
+               for _, pty := range ptys {
+                       pty.Close()
+               }
+
                s.connsLock.Lock()
                conn := s.conns[-1]
                s.connsLock.Unlock()
@@ -292,13 +303,8 @@ func (s *execWs) Do(op *operations.Operation) error {
                }
 
                attachedChildIsDead <- true
-
                wgEOF.Wait()
 
-               for _, pty := range ptys {
-                       pty.Close()
-               }
-
                metadata := shared.Jmap{"return": cmdResult}
                err = op.UpdateMetadata(metadata)
                if err != nil {
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to