Move the std_fds into initProcess, and expose them in container's State
Docker-DCO-1.1-Signed-off-by: Ross Boucher <rboucher@gmail.com> (github: boucher)
This commit is contained in:
parent
129280ac62
commit
38635c5a11
|
@ -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.
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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{"", "", ""}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue