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

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) ===
From what I've tested and understand, the `ExecInstance` function can be called with a boolean `Interactive` flag.

* When the flag is on :
  * `stderr` and `stdout` are both merged to a `stdout` reader (so there is no way to know the source)
  * unix signals can be sent to the process
* When the flag is off :
  * `stderr` and `stdout` are kept separated using two distinct readers
  * unix signals are received, but not executed

So since, I would like to keep `stderr` and `stdout` separated AND the ability to send signals to the running process, I've added some code to handle the signals in the non-interactive case.
From dfdef9e7c3dd17b1d48c85ae6eba35186f84056b Mon Sep 17 00:00:00 2001
From: Pierre Gleize <gleize.pie...@gmail.com>
Date: Fri, 28 Aug 2020 11:29:17 -0700
Subject: [PATCH] Handle signals in non-interactive sessions.

---
 lxd/instance_exec.go | 66 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/lxd/instance_exec.go b/lxd/instance_exec.go
index da59162df3..a1959a14b7 100644
--- a/lxd/instance_exec.go
+++ b/lxd/instance_exec.go
@@ -336,6 +336,72 @@ func (s *execWs) Do(op *operations.Operation) error {
                                }
                        }(i)
                }
+               wgEOF.Add(1)
+               go func() {
+                       defer wgEOF.Done()
+
+                       logger.Debug("Non-Interactive child process handler 
started")
+                       defer logger.Debug("Non-Interactive child process 
handler finished")
+
+                       select {
+                       case <-s.controlConnected:
+                               break
+                       case <-controlExit:
+                               return
+                       }
+
+                       for {
+                               s.connsLock.Lock()
+                               conn := s.conns[-1]
+                               s.connsLock.Unlock()
+
+                               mt, r, err := conn.NextReader()
+                               if mt == websocket.CloseMessage {
+                                       break
+                               }
+
+                               if err != nil {
+                                       logger.Debug("Got error getting next 
reader", log.Ctx{"err": err})
+                                       er, ok := err.(*websocket.CloseError)
+                                       if !ok {
+                                               break
+                                       }
+
+                                       if er.Code != 
websocket.CloseAbnormalClosure {
+                                               break
+                                       }
+
+                                       // If an abnormal closure occurred, 
kill the attached child.
+                                       err := cmd.Signal(unix.SIGKILL)
+                                       if err != nil {
+                                               logger.Debug("Failed to send 
SIGKILL signal", log.Ctx{"err": err})
+                                       } else {
+                                               logger.Debug("Sent SIGKILL 
signal")
+                                       }
+                                       return
+                               }
+
+                               buf, err := ioutil.ReadAll(r)
+                               if err != nil {
+                                       logger.Debug("Failed to read message", 
log.Ctx{"err": err})
+                                       break
+                               }
+
+                               command := api.InstanceExecControl{}
+
+                               if err := json.Unmarshal(buf, &command); err != 
nil {
+                                       logger.Debug("Failed to unmarshal 
control socket command", log.Ctx{"err": err})
+                                       continue
+                               }
+                               if command.Command == "signal" {
+                                       err := 
cmd.Signal(unix.Signal(command.Signal))
+                                       if err != nil {
+                                               logger.Debug("Failed forwarding 
signal", log.Ctx{"err": err, "signal": command.Signal})
+                                               continue
+                                       }
+                               }
+                       }
+               }()
        }
 
        exitCode, err := cmd.Wait()
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to