mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 06:03:57 +08:00
Store all the cgroups paths as part of the state. This simplifies entering cgroups and will be useful for
cleanups too in the future. Docker-DCO-1.1-Signed-off-by: Vishnu Kannan <vishnuk@google.com> (github: vishh)
This commit is contained in:
@@ -37,4 +37,5 @@ type Cgroup struct {
|
||||
|
||||
type ActiveCgroup interface {
|
||||
Cleanup() error
|
||||
Paths() ([]string, error)
|
||||
}
|
||||
|
||||
+12
-27
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
+11
-3
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user