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

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 eb97c1ef8f5f001d6eb4e9227eb554f9750ed04b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com>
Date: Thu, 13 Aug 2020 18:27:57 -0400
Subject: [PATCH 1/2] shared/subprocess: Add StartWithFiles
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
---
 shared/subprocess/proc.go | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/shared/subprocess/proc.go b/shared/subprocess/proc.go
index 060637e681..f78b1a1f70 100644
--- a/shared/subprocess/proc.go
+++ b/shared/subprocess/proc.go
@@ -100,6 +100,15 @@ func (p *Process) Stop() error {
 
 // Start will start the given process object
 func (p *Process) Start() error {
+       return p.start(nil)
+}
+
+// StartWithFiles will start the given process object with extra file 
descriptors
+func (p *Process) StartWithFiles(fds []*os.File) error {
+       return p.start(fds)
+}
+
+func (p *Process) start(fds []*os.File) error {
        var cmd *exec.Cmd
 
        if p.Apparmor != "" && p.hasApparmor() {
@@ -117,6 +126,10 @@ func (p *Process) Start() error {
                cmd.SysProcAttr.Credential.Gid = p.GID
        }
 
+       if fds != nil {
+               cmd.ExtraFiles = fds
+       }
+
        // Setup output capture.
        if p.Stdout != "" {
                out, err := os.Create(p.Stdout)

From 8e461e015c24fc4b3b02302fdf31fb2f55cddbca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgra...@ubuntu.com>
Date: Thu, 13 Aug 2020 18:28:13 -0400
Subject: [PATCH 2/2] lxd/forkproxy: Switch to using subprocess
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Stéphane Graber <stgra...@ubuntu.com>
---
 lxd/device/proxy.go   | 75 +++++++++++++++---------------------
 lxd/main_forkproxy.go | 90 ++++++++-----------------------------------
 2 files changed, 47 insertions(+), 118 deletions(-)

diff --git a/lxd/device/proxy.go b/lxd/device/proxy.go
index c3ef87019c..9d3420622e 100644
--- a/lxd/device/proxy.go
+++ b/lxd/device/proxy.go
@@ -2,9 +2,7 @@ package device
 
 import (
        "bufio"
-       "bytes"
        "fmt"
-       "io/ioutil"
        "net"
        "os"
        "path/filepath"
@@ -13,7 +11,6 @@ import (
        "time"
 
        "github.com/pkg/errors"
-       "golang.org/x/sys/unix"
        liblxc "gopkg.in/lxc/go-lxc.v2"
 
        deviceConfig "github.com/lxc/lxd/lxd/device/config"
@@ -24,6 +21,7 @@ import (
        "github.com/lxc/lxd/lxd/util"
        "github.com/lxc/lxd/shared"
        "github.com/lxc/lxd/shared/logger"
+       "github.com/lxc/lxd/shared/subprocess"
        "github.com/lxc/lxd/shared/validate"
 )
 
@@ -195,10 +193,9 @@ func (d *proxy) Start() (*deviceConfig.RunConfig, error) {
                        logFileName := fmt.Sprintf("proxy.%s.log", d.name)
                        logPath := filepath.Join(d.inst.LogPath(), logFileName)
 
-                       _, err = shared.RunCommandInheritFds(
-                               proxyValues.inheritFds,
-                               d.state.OS.ExecPath,
-                               "forkproxy",
+                       // Spawn the daemon using subprocess
+                       command := d.state.OS.ExecPath
+                       forkproxyargs := []string{"forkproxy",
                                "--",
                                proxyValues.listenPid,
                                proxyValues.listenPidFd,
@@ -206,28 +203,43 @@ func (d *proxy) Start() (*deviceConfig.RunConfig, error) {
                                proxyValues.connectPid,
                                proxyValues.connectPidFd,
                                proxyValues.connectAddr,
-                               logPath,
-                               pidPath,
                                proxyValues.listenAddrGID,
                                proxyValues.listenAddrUID,
                                proxyValues.listenAddrMode,
                                proxyValues.securityGID,
                                proxyValues.securityUID,
                                proxyValues.proxyProtocol,
-                       )
+                       }
+
+                       p, err := subprocess.NewProcess(command, forkproxyargs, 
logPath, logPath)
+                       if err != nil {
+                               return fmt.Errorf("Failed to create subprocess: 
%s", err)
+                       }
+
+                       err = p.StartWithFiles(proxyValues.inheritFds)
+                       if err != nil {
+                               return fmt.Errorf("Failed to run: %s %s: %v", 
command, strings.Join(forkproxyargs, " "), err)
+                       }
                        for _, file := range proxyValues.inheritFds {
                                file.Close()
                        }
 
+                       err = p.Save(pidPath)
                        if err != nil {
-                               return fmt.Errorf("Error occurred when starting 
proxy device: %s", err)
+                               // Kill Process if started, but could not save 
the file
+                               err2 := p.Stop()
+                               if err != nil {
+                                       return fmt.Errorf("Could not kill 
subprocess while handling saving error: %s: %s", err, err2)
+                               }
+
+                               return fmt.Errorf("Failed to save subprocess 
details: %s", err)
                        }
 
                        // Poll log file a few times until we see "Started" to 
indicate successful start.
                        for i := 0; i < 10; i++ {
                                started, err := d.checkProcStarted(logPath)
-
                                if err != nil {
+                                       p.Stop()
                                        return fmt.Errorf("Error occurred when 
starting proxy device: %s", err)
                                }
 
@@ -238,6 +250,7 @@ func (d *proxy) Start() (*deviceConfig.RunConfig, error) {
                                time.Sleep(time.Second)
                        }
 
+                       p.Stop()
                        return fmt.Errorf("Error occurred when starting proxy 
device, please look in %s", logPath)
                },
        }
@@ -514,45 +527,21 @@ func (d *proxy) setupProxyProcInfo() (*proxyProcInfo, 
error) {
 }
 
 func (d *proxy) killProxyProc(pidPath string) error {
-       // Get the contents of the pid file
-       contents, err := ioutil.ReadFile(pidPath)
-       if err != nil {
-               return err
-       }
-       pidString := strings.TrimSpace(string(contents))
-
-       // Check if the process still exists
-       if !shared.PathExists(fmt.Sprintf("/proc/%s", pidString)) {
-               os.Remove(pidPath)
-               return nil
-       }
-
-       // Check if it's forkdns
-       cmdArgs, err := ioutil.ReadFile(fmt.Sprintf("/proc/%s/cmdline", 
pidString))
-       if err != nil {
-               os.Remove(pidPath)
+       // If the pid file doesn't exist, there is no process to kill.
+       if !shared.PathExists(pidPath) {
                return nil
        }
 
-       cmdFields := strings.Split(string(bytes.TrimRight(cmdArgs, 
string("\x00"))), string(byte(0)))
-       if len(cmdFields) < 5 || cmdFields[1] != "forkproxy" {
-               os.Remove(pidPath)
-               return nil
-       }
-
-       // Parse the pid
-       pidInt, err := strconv.Atoi(pidString)
+       p, err := subprocess.ImportProcess(pidPath)
        if err != nil {
-               return err
+               return fmt.Errorf("Could not read pid file: %s", err)
        }
 
-       // Actually kill the process
-       err = unix.Kill(pidInt, unix.SIGKILL)
-       if err != nil {
-               return err
+       err = p.Stop()
+       if err != nil && err != subprocess.ErrNotRunning {
+               return fmt.Errorf("Unable to kill forkproxy: %s", err)
        }
 
-       // Cleanup
        os.Remove(pidPath)
        return nil
 }
diff --git a/lxd/main_forkproxy.go b/lxd/main_forkproxy.go
index 196c7c567c..49d810cb55 100644
--- a/lxd/main_forkproxy.go
+++ b/lxd/main_forkproxy.go
@@ -85,13 +85,12 @@ again:
 void forkproxy(void)
 {
        unsigned int needs_mntns = 0;
-       int connect_pid, connect_pidfd, listen_pid, listen_pidfd, log_fd;
+       int connect_pid, connect_pidfd, listen_pid, listen_pidfd;
        size_t unix_prefix_len = sizeof("unix:") - 1;
        ssize_t ret;
        pid_t pid;
-       char *connect_addr, *cur, *listen_addr, *log_path, *pid_path;
+       char *connect_addr, *cur, *listen_addr;
        int sk_fds[2] = {-EBADF, -EBADF};
-       FILE *pid_file;
 
        // Get the pid
        cur = advance_arg(false);
@@ -106,29 +105,6 @@ void forkproxy(void)
        connect_pid = atoi(advance_arg(true));
        connect_pidfd = atoi(advance_arg(true));
        connect_addr = advance_arg(true);
-       log_path = advance_arg(true);
-       pid_path = advance_arg(true);
-
-       close(STDIN_FILENO);
-       log_fd = open(log_path, O_WRONLY | O_CREAT | O_CLOEXEC | O_TRUNC, 0600);
-       if (log_fd < 0)
-               _exit(EXIT_FAILURE);
-
-       ret = dup3(log_fd, STDOUT_FILENO, O_CLOEXEC);
-       if (ret < 0)
-               _exit(EXIT_FAILURE);
-
-       ret = dup3(log_fd, STDERR_FILENO, O_CLOEXEC);
-       if (ret < 0)
-               _exit(EXIT_FAILURE);
-
-       pid_file = fopen(pid_path, "we+");
-       if (!pid_file) {
-               fprintf(stderr,
-                       "%s - Failed to create pid file for proxy daemon\n",
-                       strerror(errno));
-               _exit(EXIT_FAILURE);
-       }
 
        if (strncmp(listen_addr, "udp:", sizeof("udp:") - 1) == 0 &&
            strncmp(connect_addr, "udp:", sizeof("udp:") - 1) != 0) {
@@ -166,7 +142,6 @@ void forkproxy(void)
 
                whoami = FORKPROXY_CHILD;
 
-               fclose(pid_file);
                ret = close(sk_fds[0]);
                if (ret < 0)
                        fprintf(stderr, "%s - Failed to close fd %d\n",
@@ -269,41 +244,6 @@ void forkproxy(void)
                // can just rely on init doing it's job and reaping the zombie
                // process. So, technically unsatisfying but pragmatically
                // correct.
-
-               // daemonize
-               pid = fork();
-               if (pid < 0)
-                       _exit(EXIT_FAILURE);
-
-               if (pid != 0) {
-                       ret = wait_for_pid(pid);
-                       if (ret < 0)
-                               _exit(EXIT_FAILURE);
-
-                       _exit(EXIT_SUCCESS);
-               }
-
-               pid = fork();
-               if (pid < 0)
-                       _exit(EXIT_FAILURE);
-
-               if (pid != 0) {
-                       ret = fprintf(pid_file, "%d", pid);
-                       fclose(pid_file);
-                       if (ret < 0) {
-                               fprintf(stderr, "Failed to write proxy daemon 
pid %d to \"%s\"\n",
-                                       pid, pid_path);
-                               ret = EXIT_FAILURE;
-                       }
-                       close(STDOUT_FILENO);
-                       close(STDERR_FILENO);
-                       _exit(EXIT_SUCCESS);
-               }
-
-               ret = setsid();
-               if (ret < 0)
-                       fprintf(stderr, "%s - Failed to setsid in proxy 
daemon\n",
-                               strerror(errno));
        }
 }
 */
@@ -338,7 +278,7 @@ func (c *cmdForkproxy) Command() *cobra.Command {
   container, connecting one side to the host and the other to the
   container.
 `
-       cmd.Args = cobra.ExactArgs(14)
+       cmd.Args = cobra.ExactArgs(12)
        cmd.RunE = c.Run
        cmd.Hidden = true
 
@@ -459,7 +399,7 @@ func (c *cmdForkproxy) Run(cmd *cobra.Command, args 
[]string) error {
        }
 
        // Sanity checks
-       if len(args) != 14 {
+       if len(args) != 12 {
                cmd.Help()
 
                if len(args) == 0 {
@@ -529,16 +469,16 @@ func (c *cmdForkproxy) Run(cmd *cobra.Command, args 
[]string) error {
                        var err error
 
                        listenAddrGID := -1
-                       if args[8] != "" {
-                               listenAddrGID, err = strconv.Atoi(args[8])
+                       if args[6] != "" {
+                               listenAddrGID, err = strconv.Atoi(args[6])
                                if err != nil {
                                        return err
                                }
                        }
 
                        listenAddrUID := -1
-                       if args[9] != "" {
-                               listenAddrUID, err = strconv.Atoi(args[9])
+                       if args[7] != "" {
+                               listenAddrUID, err = strconv.Atoi(args[7])
                                if err != nil {
                                        return err
                                }
@@ -552,8 +492,8 @@ func (c *cmdForkproxy) Run(cmd *cobra.Command, args 
[]string) error {
                        }
 
                        var listenAddrMode os.FileMode
-                       if args[10] != "" {
-                               tmp, err := strconv.ParseUint(args[10], 8, 0)
+                       if args[8] != "" {
+                               tmp, err := strconv.ParseUint(args[8], 8, 0)
                                if err != nil {
                                        return err
                                }
@@ -621,16 +561,16 @@ func (c *cmdForkproxy) Run(cmd *cobra.Command, args 
[]string) error {
 
        // Drop privilege if requested
        gid := uint64(0)
-       if args[11] != "" {
-               gid, err = strconv.ParseUint(args[11], 10, 32)
+       if args[9] != "" {
+               gid, err = strconv.ParseUint(args[9], 10, 32)
                if err != nil {
                        return err
                }
        }
 
        uid := uint64(0)
-       if args[12] != "" {
-               uid, err = strconv.ParseUint(args[12], 10, 32)
+       if args[10] != "" {
+               uid, err = strconv.ParseUint(args[10], 10, 32)
                if err != nil {
                        return err
                }
@@ -710,7 +650,7 @@ func (c *cmdForkproxy) Run(cmd *cobra.Command, args 
[]string) error {
                                continue
                        }
 
-                       err := listenerInstance(epFd, lAddr, cAddr, curFd, 
srcConn, args[13] == "true")
+                       err := listenerInstance(epFd, lAddr, cAddr, curFd, 
srcConn, args[11] == "true")
                        if err != nil {
                                fmt.Printf("Warning: Failed to prepare new 
listener instance: %s\n", err)
                        }
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to