diff --git a/cgroups/cgroups.go b/cgroups/cgroups.go index 64ece568c..26fef4540 100644 --- a/cgroups/cgroups.go +++ b/cgroups/cgroups.go @@ -37,4 +37,5 @@ type Cgroup struct { type ActiveCgroup interface { Cleanup() error + Paths() ([]string, error) } diff --git a/cgroups/fs/apply_raw.go b/cgroups/fs/apply_raw.go index bf01df5dc..9a73dcdeb 100644 --- a/cgroups/fs/apply_raw.go +++ b/cgroups/fs/apply_raw.go @@ -120,33 +120,6 @@ func GetPids(c *cgroups.Cgroup) ([]int, error) { return cgroups.ReadProcsFile(dir) } -func EnterPid(c *cgroups.Cgroup, pid int) error { - d, err := getCgroupData(c, pid) - if err != nil { - return err - } - - for sysname := range subsystems { - path, err := d.path(sysname) - if err != nil { - // Don't fail if a cgroup hierarchy was not found, just skip this subsystem - if err == cgroups.ErrNotFound { - continue - } - - return err - } - - if PathExists(path) { - if _, err := d.join(sysname); err != nil { - return err - } - } - } - - return nil -} - func getCgroupData(c *cgroups.Cgroup, pid int) (*data, error) { // we can pick any subsystem to find the root cgroupRoot, err := cgroups.FindCgroupMountpoint("cpu") @@ -180,6 +153,18 @@ func (raw *data) parent(subsystem string) (string, error) { return filepath.Join(raw.root, subsystem, initPath), nil } +func (raw *data) Paths() ([]string, error) { + var paths []string + for sysname := range subsystems { + path, err := raw.path(sysname) + if err != nil { + return nil, err + } + paths = append(paths, path) + } + return paths, nil +} + func (raw *data) path(subsystem string) (string, error) { // If the cgroup name/path is absolute do not look relative to the cgroup of the init process. if filepath.IsAbs(raw.cgroup) { diff --git a/cgroups/fs/utils.go b/cgroups/fs/utils.go index b54a8b992..f65622a80 100644 --- a/cgroups/fs/utils.go +++ b/cgroups/fs/utils.go @@ -4,7 +4,6 @@ import ( "errors" "fmt" "io/ioutil" - "os" "path/filepath" "strconv" "strings" @@ -39,10 +38,3 @@ func getCgroupParamInt(cgroupPath, cgroupFile string) (uint64, error) { } return strconv.ParseUint(strings.TrimSpace(string(contents)), 10, 64) } - -func PathExists(path string) bool { - if _, err := os.Stat(path); err != nil { - return false - } - return true -} diff --git a/cgroups/systemd/apply_systemd.go b/cgroups/systemd/apply_systemd.go index 1849a8def..db06e1b65 100644 --- a/cgroups/systemd/apply_systemd.go +++ b/cgroups/systemd/apply_systemd.go @@ -320,6 +320,10 @@ func writeFile(dir, file, data string) error { return ioutil.WriteFile(filepath.Join(dir, file), []byte(data), 0700) } +func (c *systemdCgroup) Paths() ([]string, error) { + return c.cleanupDirs, nil +} + func (c *systemdCgroup) Cleanup() error { // systemd cleans up, we don't need to do much @@ -437,26 +441,3 @@ func GetStats(c *cgroups.Cgroup) (*cgroups.Stats, error) { return stats, nil } - -func EnterPid(c *cgroups.Cgroup, pid int) error { - for sysname := range subsystems { - subsystemPath, err := getSubsystemPath(c, sysname) - if err != nil { - // Don't fail if a cgroup hierarchy was not found, just skip this subsystem - if err == cgroups.ErrNotFound { - continue - } - - return err - } - - if fs.PathExists(subsystemPath) { - if err := ioutil.WriteFile(filepath.Join(subsystemPath, fs.CgroupProcesses), - []byte(strconv.Itoa(pid)), 0700); err != nil { - return err - } - } - } - - return nil -} diff --git a/cgroups/utils.go b/cgroups/utils.go index ce5c4f336..4220267b8 100644 --- a/cgroups/utils.go +++ b/cgroups/utils.go @@ -4,6 +4,7 @@ import ( "bufio" "fmt" "io" + "io/ioutil" "os" "path/filepath" "strconv" @@ -166,3 +167,23 @@ func parseCgroupFile(subsystem string, r io.Reader) (string, error) { } return "", ErrNotFound } + +func pathExists(path string) bool { + if _, err := os.Stat(path); err != nil { + return false + } + return true +} + +func EnterPid(cgroupPaths []string, pid int) error { + for _, path := range cgroupPaths { + if pathExists(path) { + if err := ioutil.WriteFile(filepath.Join(path, "cgroup.procs"), + []byte(strconv.Itoa(pid)), 0700); err != nil { + return err + } + } + } + + return nil +} diff --git a/namespaces/exec.go b/namespaces/exec.go index c9b2037cc..eb92a71e7 100644 --- a/namespaces/exec.go +++ b/namespaces/exec.go @@ -56,14 +56,21 @@ func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Wri // Do this before syncing with child so that no children // can escape the cgroup - cleaner, err := SetupCgroups(container, command.Process.Pid) + cgroupRef, err := SetupCgroups(container, command.Process.Pid) if err != nil { command.Process.Kill() command.Wait() return -1, err } - if cleaner != nil { - defer cleaner.Cleanup() + if cgroupRef != nil { + defer cgroupRef.Cleanup() + } + + cgroupPaths, err := cgroupRef.Paths() + if err != nil { + command.Process.Kill() + command.Wait() + return -1, err } var networkState network.NetworkState @@ -77,6 +84,7 @@ func Exec(container *libcontainer.Config, stdin io.Reader, stdout, stderr io.Wri InitPid: command.Process.Pid, InitStartTime: started, NetworkState: networkState, + CgroupPaths: cgroupPaths, } if err := libcontainer.SaveState(dataPath, state); err != nil { diff --git a/namespaces/execin.go b/namespaces/execin.go index 1d1ac09ab..8b81edecb 100644 --- a/namespaces/execin.go +++ b/namespaces/execin.go @@ -12,8 +12,7 @@ import ( "syscall" "github.com/docker/libcontainer" - "github.com/docker/libcontainer/cgroups/fs" - "github.com/docker/libcontainer/cgroups/systemd" + "github.com/docker/libcontainer/cgroups" "github.com/docker/libcontainer/label" "github.com/docker/libcontainer/syncpipe" "github.com/docker/libcontainer/system" @@ -62,7 +61,7 @@ func ExecIn(container *libcontainer.Config, state *libcontainer.State, userArgs pipe.CloseChild() // Enter cgroups. - if err := EnterCgroups(container, cmd.Process.Pid); err != nil { + if err := EnterCgroups(state, cmd.Process.Pid); err != nil { return -1, err } @@ -110,9 +109,6 @@ func FinalizeSetns(container *libcontainer.Config, args []string) error { panic("unreachable") } -func EnterCgroups(container *libcontainer.Config, pid int) error { - if systemd.UseSystemd() { - return systemd.EnterPid(container.Cgroups, pid) - } - return fs.EnterPid(container.Cgroups, pid) +func EnterCgroups(state *libcontainer.State, pid int) error { + return cgroups.EnterPid(state.CgroupPaths, pid) } diff --git a/state.go b/state.go index ee5d14d2e..e7d03bc07 100644 --- a/state.go +++ b/state.go @@ -18,6 +18,9 @@ type State struct { // Network runtime state. NetworkState network.NetworkState `json:"network_state,omitempty"` + + // Path to all the cgroup dirs. + CgroupPaths []string `json:"cgroup_paths,omitempty"` } // The running state of the container.