From 38635c5a11af7f638062de17e5c8a2d0c5d465f6 Mon Sep 17 00:00:00 2001 From: boucher Date: Tue, 28 Apr 2015 12:13:57 -0700 Subject: [PATCH] Move the std_fds into initProcess, and expose them in container's State Docker-DCO-1.1-Signed-off-by: Ross Boucher (github: boucher) --- container.go | 3 +++ container_linux.go | 10 ++-------- process_linux.go | 41 ++++++++++++++++++++++------------------- restored_process.go | 8 ++++++++ 4 files changed, 35 insertions(+), 27 deletions(-) diff --git a/container.go b/container.go index 9faa7926..cb4e25b1 100644 --- a/container.go +++ b/container.go @@ -49,6 +49,9 @@ type State struct { // Config is the container's configuration. Config configs.Config `json:"config"` + + // Container's standard descriptors (std{in,out,err}), needed for checkpoint and restore + StdFds [3]string `json:"std_fds,omitempty"` } // A libcontainer container object. diff --git a/container_linux.go b/container_linux.go index 61be6942..c99de565 100644 --- a/container_linux.go +++ b/container_linux.go @@ -371,7 +371,7 @@ func (c *linuxContainer) Checkpoint(criuOpts *CriuOpts) error { // Write the FD info to a file in the image directory - fdsJSON, err := json.Marshal(c.config.StdFds) + fdsJSON, err := json.Marshal(c.initProcess.stdFds()) if err != nil { return err } @@ -558,13 +558,6 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts * log.Warn(st.String()) }() - if process != nil { - err = saveStdPipes(cmd.Process.Pid, c.config) - if err != nil { - return err - } - } - data, err := proto.Marshal(req) if err != nil { return err @@ -770,6 +763,7 @@ func (c *linuxContainer) currentState() (*State, error) { InitProcessStartTime: startTime, CgroupPaths: c.cgroupManager.GetPaths(), NamespacePaths: make(map[configs.NamespaceType]string), + StdFds: c.initProcess.stdFds(), } for _, ns := range c.config.Namespaces { state.NamespacePaths[ns.Type] = ns.GetPath(c.initProcess.pid()) diff --git a/process_linux.go b/process_linux.go index 47044c9b..5924161f 100644 --- a/process_linux.go +++ b/process_linux.go @@ -13,7 +13,6 @@ import ( "syscall" "github.com/docker/libcontainer/cgroups" - "github.com/docker/libcontainer/configs" "github.com/docker/libcontainer/system" ) @@ -34,6 +33,8 @@ type parentProcess interface { startTime() (string, error) signal(os.Signal) error + + stdFds() [3]string } type setnsProcess struct { @@ -145,18 +146,28 @@ func (p *setnsProcess) pid() int { return p.cmd.Process.Pid } +func (p *setnsProcess) stdFds() [3]string { + return [3]string{"", "", ""} +} + type initProcess struct { cmd *exec.Cmd parentPipe *os.File childPipe *os.File config *initConfig manager cgroups.Manager + container *linuxContainer + fds [3]string } func (p *initProcess) pid() int { return p.cmd.Process.Pid } +func (p *initProcess) stdFds() [3]string { + return p.fds +} + func (p *initProcess) start() error { defer p.parentPipe.Close() err := p.cmd.Start() @@ -167,9 +178,17 @@ func (p *initProcess) start() error { // Save the standard descriptor names before the container process // can potentially move them (e.g., via dup2()). If we don't do this now, // we won't know at checkpoint time which file descriptor to look up. - if err = saveStdPipes(p.pid(), p.config.Config); err != nil { - return newSystemError(err) + // we need this info to restore the container + dirPath := filepath.Join("/proc", strconv.Itoa(p.pid()), "/fd") + for i := 0; i < 3; i++ { + f := filepath.Join(dirPath, strconv.Itoa(i)) + target, err := os.Readlink(f) + if err != nil { + return newSystemError(err) + } + p.fds[i] = target } + // Do this before syncing with child so that no children // can escape the cgroup if err := p.manager.Apply(p.pid()); err != nil { @@ -259,19 +278,3 @@ func (p *initProcess) signal(sig os.Signal) error { } return syscall.Kill(p.cmd.Process.Pid, s) } - -// Save process's std{in,out,err} file names as these will be -// removed if/when the container is checkpointed. We will need -// this info to restore the container. -func saveStdPipes(pid int, config *configs.Config) error { - dirPath := filepath.Join("/proc", strconv.Itoa(pid), "/fd") - for i := 0; i < 3; i++ { - f := filepath.Join(dirPath, strconv.Itoa(i)) - target, err := os.Readlink(f) - if err != nil { - return err - } - config.StdFds[i] = target - } - return nil -} diff --git a/restored_process.go b/restored_process.go index ae60e6ef..12408d77 100644 --- a/restored_process.go +++ b/restored_process.go @@ -66,6 +66,10 @@ func (p *restoredProcess) signal(s os.Signal) error { return p.proc.Signal(s) } +func (p *restoredProcess) stdFds() [3]string { + return [3]string{"", "", ""} +} + // nonChildProcess represents a process where the calling process is not // the parent process. This process is created when a factory loads a container from // a persisted state. @@ -97,3 +101,7 @@ func (p *nonChildProcess) startTime() (string, error) { func (p *nonChildProcess) signal(s os.Signal) error { return newGenericError(fmt.Errorf("restored process cannot be signaled"), SystemError) } + +func (p *nonChildProcess) stdFds() [3]string { + return [3]string{"", "", ""} +}