diff --git a/go.mod b/go.mod index 3e4e4cfc5..5338147a7 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/container-orchestrated-devices/container-device-interface v0.5.1 github.com/containerd/aufs v1.0.0 github.com/containerd/btrfs v1.0.0 - github.com/containerd/cgroups/v3 v3.0.0-20221112182753-e8802a182774 + github.com/containerd/cgroups/v3 v3.0.0 github.com/containerd/console v1.0.3 github.com/containerd/continuity v0.3.0 github.com/containerd/fifo v1.0.0 diff --git a/go.sum b/go.sum index e06b150ac..0ab4bada9 100644 --- a/go.sum +++ b/go.sum @@ -197,8 +197,8 @@ github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f2 github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= -github.com/containerd/cgroups/v3 v3.0.0-20221112182753-e8802a182774 h1:Tej/o6wjJ3icV9qkPopNXJxk2oeVAmRc7JL0q5JeUq8= -github.com/containerd/cgroups/v3 v3.0.0-20221112182753-e8802a182774/go.mod h1:/vtwk1VXrtoa5AaZLkypuOJgA/6DyPMZHJPGQNtlHnw= +github.com/containerd/cgroups/v3 v3.0.0 h1:EzSABvwGkHxdwtZsNBWl8M3iNh+0lMJb/fmtyoSXlsc= +github.com/containerd/cgroups/v3 v3.0.0/go.mod h1:/vtwk1VXrtoa5AaZLkypuOJgA/6DyPMZHJPGQNtlHnw= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= diff --git a/integration/client/go.mod b/integration/client/go.mod index aa7976672..e62cb7e76 100644 --- a/integration/client/go.mod +++ b/integration/client/go.mod @@ -6,7 +6,7 @@ require ( github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 github.com/Microsoft/hcsshim v0.10.0-rc.4 github.com/Microsoft/hcsshim/test v0.0.0-20210408205431-da33ecd607e1 - github.com/containerd/cgroups/v3 v3.0.0-20221112182753-e8802a182774 + github.com/containerd/cgroups/v3 v3.0.0 github.com/containerd/containerd v1.7.0-beta.0 // see replace; the actual version of containerd is replaced with the code at the root of this repository github.com/containerd/go-runc v1.0.0 github.com/containerd/ttrpc v1.1.1-0.20220420014843-944ef4a40df3 diff --git a/integration/client/go.sum b/integration/client/go.sum index 999ff536e..739486263 100644 --- a/integration/client/go.sum +++ b/integration/client/go.sum @@ -499,8 +499,8 @@ github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f2 github.com/containerd/cgroups v1.0.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8= github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA= -github.com/containerd/cgroups/v3 v3.0.0-20221112182753-e8802a182774 h1:Tej/o6wjJ3icV9qkPopNXJxk2oeVAmRc7JL0q5JeUq8= -github.com/containerd/cgroups/v3 v3.0.0-20221112182753-e8802a182774/go.mod h1:/vtwk1VXrtoa5AaZLkypuOJgA/6DyPMZHJPGQNtlHnw= +github.com/containerd/cgroups/v3 v3.0.0 h1:EzSABvwGkHxdwtZsNBWl8M3iNh+0lMJb/fmtyoSXlsc= +github.com/containerd/cgroups/v3 v3.0.0/go.mod h1:/vtwk1VXrtoa5AaZLkypuOJgA/6DyPMZHJPGQNtlHnw= github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= diff --git a/vendor/github.com/containerd/cgroups/v3/README.md b/vendor/github.com/containerd/cgroups/v3/README.md index ed8231200..a90b87266 100644 --- a/vendor/github.com/containerd/cgroups/v3/README.md +++ b/vendor/github.com/containerd/cgroups/v3/README.md @@ -188,6 +188,19 @@ if err != nil { } ``` +### Kill all processes in a cgroup + +```go +m, err := cgroup2.LoadSystemd("/", "my-cgroup-abc.slice") +if err != nil { + return err +} +err = m.Kill() +if err != nil { + return err +} +``` + ### Attention All static path should not include `/sys/fs/cgroup/` prefix, it should start with your own cgroups name diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup1/memory.go b/vendor/github.com/containerd/cgroups/v3/cgroup1/memory.go index 484f9175c..e84ec2b3c 100644 --- a/vendor/github.com/containerd/cgroups/v3/cgroup1/memory.go +++ b/vendor/github.com/containerd/cgroups/v3/cgroup1/memory.go @@ -43,7 +43,7 @@ type memoryThresholdEvent struct { swap bool } -// MemoryThresholdEvent returns a new memory threshold event to be used with RegisterMemoryEvent. +// MemoryThresholdEvent returns a new [MemoryEvent] representing the memory threshold set. // If swap is true, the event will be registered using memory.memsw.usage_in_bytes func MemoryThresholdEvent(threshold uint64, swap bool) MemoryEvent { return &memoryThresholdEvent{ @@ -83,7 +83,7 @@ type memoryPressureEvent struct { hierarchy EventNotificationMode } -// MemoryPressureEvent returns a new memory pressure event to be used with RegisterMemoryEvent. +// MemoryPressureEvent returns a new [MemoryEvent] representing the memory pressure set. func MemoryPressureEvent(pressureLevel MemoryPressureLevel, hierarchy EventNotificationMode) MemoryEvent { return &memoryPressureEvent{ pressureLevel, diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/manager.go b/vendor/github.com/containerd/cgroups/v3/cgroup2/manager.go index cef8cd9b2..fc9fcf453 100644 --- a/vendor/github.com/containerd/cgroups/v3/cgroup2/manager.go +++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/manager.go @@ -42,6 +42,7 @@ import ( const ( subtreeControl = "cgroup.subtree_control" controllersFile = "cgroup.controllers" + killFile = "cgroup.kill" defaultCgroup2Path = "/sys/fs/cgroup" defaultSlice = "system.slice" ) @@ -144,20 +145,11 @@ func (c *Value) write(path string, perm os.FileMode) error { return ErrInvalidFormat } - // Retry writes on EINTR; see: - // https://github.com/golang/go/issues/38033 - for { - err := os.WriteFile( - filepath.Join(path, c.filename), - data, - perm, - ) - if err == nil { - return nil - } else if !errors.Is(err, syscall.EINTR) { - return err - } - } + return os.WriteFile( + filepath.Join(path, c.filename), + data, + perm, + ) } func writeValues(path string, values []Value) error { @@ -202,7 +194,7 @@ type InitConfig struct { type InitOpts func(c *InitConfig) error -// WithMountpoint sets the unified mountpoint. The deault path is /sys/fs/cgroup. +// WithMountpoint sets the unified mountpoint. The default path is /sys/fs/cgroup. func WithMountpoint(path string) InitOpts { return func(c *InitConfig) error { c.mountpoint = path @@ -366,6 +358,86 @@ func (c *Manager) AddThread(tid uint64) error { return writeValues(c.path, []Value{v}) } +// Kill will try to forcibly exit all of the processes in the cgroup. This is +// equivalent to sending a SIGKILL to every process. On kernels 5.14 and greater +// this will use the cgroup.kill file, on anything that doesn't have the cgroup.kill +// file, a manual process of freezing -> sending a SIGKILL to every process -> thawing +// will be used. +func (c *Manager) Kill() error { + v := Value{ + filename: killFile, + value: "1", + } + err := writeValues(c.path, []Value{v}) + if err == nil { + return nil + } + logrus.Warnf("falling back to slower kill implementation: %s", err) + // Fallback to slow method. + return c.fallbackKill() +} + +// fallbackKill is a slower fallback to the more modern (kernels 5.14+) +// approach of writing to the cgroup.kill file. This is heavily pulled +// from runc's same approach (in signalAllProcesses), with the only differences +// being this is just tailored to the API exposed in this library, and we don't +// need to care about signals other than SIGKILL. +// +// https://github.com/opencontainers/runc/blob/8da0a0b5675764feaaaaad466f6567a9983fcd08/libcontainer/init_linux.go#L523-L529 +func (c *Manager) fallbackKill() error { + if err := c.Freeze(); err != nil { + logrus.Warn(err) + } + pids, err := c.Procs(true) + if err != nil { + if err := c.Thaw(); err != nil { + logrus.Warn(err) + } + return err + } + var procs []*os.Process + for _, pid := range pids { + p, err := os.FindProcess(int(pid)) + if err != nil { + logrus.Warn(err) + continue + } + procs = append(procs, p) + if err := p.Signal(unix.SIGKILL); err != nil { + logrus.Warn(err) + } + } + if err := c.Thaw(); err != nil { + logrus.Warn(err) + } + + subreaper, err := getSubreaper() + if err != nil { + // The error here means that PR_GET_CHILD_SUBREAPER is not + // supported because this code might run on a kernel older + // than 3.4. We don't want to throw an error in that case, + // and we simplify things, considering there is no subreaper + // set. + subreaper = 0 + } + + for _, p := range procs { + // In case a subreaper has been setup, this code must not + // wait for the process. Otherwise, we cannot be sure the + // current process will be reaped by the subreaper, while + // the subreaper might be waiting for this process in order + // to retrieve its exit code. + if subreaper == 0 { + if _, err := p.Wait(); err != nil { + if !errors.Is(err, unix.ECHILD) { + logrus.Warnf("wait on pid %d failed: %s", p.Pid, err) + } + } + } + } + return nil +} + func (c *Manager) Delete() error { // kernel prevents cgroups with running process from being removed, check the tree is empty processes, err := c.Procs(true) @@ -763,7 +835,8 @@ func setDevices(path string, devices []specs.LinuxDeviceCgroup) error { // the reason this is necessary is because the "-" character has a special meaning in // systemd slice. For example, when creating a slice called "my-group-112233.slice", // systemd will create a hierarchy like this: -// /sys/fs/cgroup/my.slice/my-group.slice/my-group-112233.slice +// +// /sys/fs/cgroup/my.slice/my-group.slice/my-group-112233.slice func getSystemdFullPath(slice, group string) string { return filepath.Join(defaultCgroup2Path, dashesToPath(slice), dashesToPath(group)) } diff --git a/vendor/github.com/containerd/cgroups/v3/cgroup2/utils.go b/vendor/github.com/containerd/cgroups/v3/cgroup2/utils.go index 74bef4ac5..776501830 100644 --- a/vendor/github.com/containerd/cgroups/v3/cgroup2/utils.go +++ b/vendor/github.com/containerd/cgroups/v3/cgroup2/utils.go @@ -26,12 +26,14 @@ import ( "strconv" "strings" "time" + "unsafe" "github.com/containerd/cgroups/v3/cgroup2/stats" "github.com/godbus/dbus/v5" "github.com/opencontainers/runtime-spec/specs-go" "github.com/sirupsen/logrus" + "golang.org/x/sys/unix" ) const ( @@ -434,3 +436,11 @@ func readHugeTlbStats(path string) []*stats.HugeTlbStat { } return usage } + +func getSubreaper() (int, error) { + var i uintptr + if err := unix.Prctl(unix.PR_GET_CHILD_SUBREAPER, uintptr(unsafe.Pointer(&i)), 0, 0, 0); err != nil { + return -1, err + } + return int(i), nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index edb9efb96..83dce22f0 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -92,7 +92,7 @@ github.com/containerd/btrfs # github.com/containerd/cgroups v1.0.4 ## explicit; go 1.17 github.com/containerd/cgroups/stats/v1 -# github.com/containerd/cgroups/v3 v3.0.0-20221112182753-e8802a182774 +# github.com/containerd/cgroups/v3 v3.0.0 ## explicit; go 1.17 github.com/containerd/cgroups/v3 github.com/containerd/cgroups/v3/cgroup1