Skip to content

Instantly share code, notes, and snippets.

@boucher
Created April 28, 2015 18:49
Show Gist options
  • Save boucher/08faf44aa51934883de6 to your computer and use it in GitHub Desktop.
Save boucher/08faf44aa51934883de6 to your computer and use it in GitHub Desktop.
diff --git a/configs/config.go b/configs/config.go
index 33c9fc0..b07f252 100644
--- a/configs/config.go
+++ b/configs/config.go
@@ -96,9 +96,6 @@ type Config struct {
// ReadonlyPaths specifies paths within the container's rootfs to remount as read-only
// so that these files prevent any writes.
ReadonlyPaths []string `json:"readonly_paths"`
-
- // Container's standard descriptors (std{in,out,err}), needed for checkpoint and restore
- StdFds [3]string `json:"ext_pipes,omitempty"`
}
// Gets the root uid for the process on host which could be non-zero
diff --git a/container.go b/container.go
index b954272..5698361 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:"ext_pipes,omitempty"`
}
// A libcontainer container object.
diff --git a/container_linux.go b/container_linux.go
index 6011f39..1b6ad54 100644
--- a/container_linux.go
+++ b/container_linux.go
@@ -369,7 +369,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
}
@@ -557,7 +558,7 @@ func (c *linuxContainer) criuSwrk(process *Process, req *criurpc.CriuReq, opts *
}()
if process != nil {
- err = saveStdPipes(cmd.Process.Pid, c.config)
+ err = c.initProcess.saveStdPipes()
if err != nil {
return err
}
@@ -768,6 +769,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 e3934a3..0f15bd8 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,10 @@ type parentProcess interface {
startTime() (string, error)
signal(os.Signal) error
+
+ stdFds() [3]string
+
+ saveStdPipes() error
}
type setnsProcess struct {
@@ -142,18 +145,32 @@ func (p *setnsProcess) pid() int {
return p.cmd.Process.Pid
}
+func (p *setnsProcess) stdFds() [3]string {
+ return [3]string{"", "", ""}
+}
+
+func (p *setnsProcess) saveStdPipes() error {
+ return nil
+}
+
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()
@@ -164,7 +181,7 @@ 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 {
+ if err = p.saveStdPipes(); err != nil {
return newSystemError(err)
}
// Do this before syncing with child so that no children
@@ -260,15 +277,15 @@ func (p *initProcess) signal(sig os.Signal) error {
// 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")
+func (p *initProcess) saveStdPipes() error {
+ 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 err
}
- config.StdFds[i] = target
+ p.fds[i] = target
}
return nil
}
diff --git a/restored_process.go b/restored_process.go
index ae60e6e..629eab9 100644
--- a/restored_process.go
+++ b/restored_process.go
@@ -66,6 +66,14 @@ func (p *restoredProcess) signal(s os.Signal) error {
return p.proc.Signal(s)
}
+func (p *restoredProcess) stdFds() [3]string {
+ return [3]string{"", "", ""}
+}
+
+func (p *restoredProcess) saveStdPipes() error {
+ return nil
+}
+
// 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 +105,11 @@ 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{"", "", ""}
+}
+
+func (p *nonChildProcess) saveStdPipes() error {
+ return newGenericError(fmt.Errorf("restored process cannot save stdfds"), SystemError)
+}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment