diff options
Diffstat (limited to 'pkg/rootlessport')
-rw-r--r-- | pkg/rootlessport/rootlessport_linux.go | 65 |
1 files changed, 55 insertions, 10 deletions
diff --git a/pkg/rootlessport/rootlessport_linux.go b/pkg/rootlessport/rootlessport_linux.go index 3e678d33a..1c1ed39df 100644 --- a/pkg/rootlessport/rootlessport_linux.go +++ b/pkg/rootlessport/rootlessport_linux.go @@ -19,7 +19,7 @@ import ( "io/ioutil" "os" "os/exec" - "syscall" + "os/signal" "github.com/containernetworking/plugins/pkg/ns" "github.com/containers/storage/pkg/reexec" @@ -29,6 +29,7 @@ import ( rkbuiltin "github.com/rootless-containers/rootlesskit/pkg/port/builtin" rkportutil "github.com/rootless-containers/rootlesskit/pkg/port/portutil" "github.com/sirupsen/logrus" + "golang.org/x/sys/unix" ) const ( @@ -101,6 +102,28 @@ func parent() error { return err } + sigC := make(chan os.Signal, 1) + signal.Notify(sigC, unix.SIGPIPE) + defer func() { + // dummy signal to terminate the goroutine + sigC <- unix.SIGKILL + }() + go func() { + defer func() { + signal.Stop(sigC) + close(sigC) + }() + + s := <-sigC + if s == unix.SIGPIPE { + if f, err := os.OpenFile("/dev/null", os.O_WRONLY, 0755); err == nil { + unix.Dup2(int(f.Fd()), 1) // nolint:errcheck + unix.Dup2(int(f.Fd()), 2) // nolint:errcheck + f.Close() + } + } + }() + // create the parent driver stateDir, err := ioutil.TempDir(cfg.TmpDir, "rootlessport") if err != nil { @@ -122,6 +145,7 @@ func parent() error { logrus.WithError(driverErr).Warn("parent driver exited") } errCh <- driverErr + close(errCh) }() opaque := driver.OpaqueForChild() logrus.Infof("opaque=%+v", opaque) @@ -142,15 +166,12 @@ func parent() error { }() // reexec the child process in the child netns - cmd := exec.Command(fmt.Sprintf("/proc/%d/exe", os.Getpid())) + cmd := exec.Command("/proc/self/exe") cmd.Args = []string{reexecChildKey} cmd.Stdin = childQuitR cmd.Stdout = &logrusWriter{prefix: "child"} cmd.Stderr = cmd.Stdout cmd.Env = append(os.Environ(), reexecChildEnvOpaque+"="+string(opaqueJSON)) - cmd.SysProcAttr = &syscall.SysProcAttr{ - Pdeathsig: syscall.SIGTERM, - } childNS, err := ns.GetNS(cfg.NetNSPath) if err != nil { return err @@ -162,14 +183,38 @@ func parent() error { return err } + childErrCh := make(chan error) + go func() { + err := cmd.Wait() + childErrCh <- err + close(childErrCh) + }() + + defer func() { + if err := unix.Kill(cmd.Process.Pid, unix.SIGTERM); err != nil { + logrus.WithError(err).Warn("kill child process") + } + }() + logrus.Info("waiting for initComplete") // wait for the child to connect to the parent - select { - case <-initComplete: - logrus.Infof("initComplete is closed; parent and child established the communication channel") - case err := <-errCh: - return err +outer: + for { + select { + case <-initComplete: + logrus.Infof("initComplete is closed; parent and child established the communication channel") + break outer + case err := <-childErrCh: + if err != nil { + return err + } + case err := <-errCh: + if err != nil { + return err + } + } } + defer func() { logrus.Info("stopping parent driver") quit <- struct{}{} |