go.mod: github.com/containerd/cgroups/v3 v3.0.0

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
This commit is contained in:
Akihiro Suda 2023-01-30 11:57:27 +09:00
parent 967979efdc
commit 306db3e707
No known key found for this signature in database
GPG Key ID: 49524C6F9F638F1A
9 changed files with 121 additions and 25 deletions

2
go.mod
View File

@ -10,7 +10,7 @@ require (
github.com/container-orchestrated-devices/container-device-interface v0.5.1 github.com/container-orchestrated-devices/container-device-interface v0.5.1
github.com/containerd/aufs v1.0.0 github.com/containerd/aufs v1.0.0
github.com/containerd/btrfs 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/console v1.0.3
github.com/containerd/continuity v0.3.0 github.com/containerd/continuity v0.3.0
github.com/containerd/fifo v1.0.0 github.com/containerd/fifo v1.0.0

4
go.sum
View File

@ -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.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8=
github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= 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 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 h1:EzSABvwGkHxdwtZsNBWl8M3iNh+0lMJb/fmtyoSXlsc=
github.com/containerd/cgroups/v3 v3.0.0-20221112182753-e8802a182774/go.mod h1:/vtwk1VXrtoa5AaZLkypuOJgA/6DyPMZHJPGQNtlHnw= 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-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-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE=

View File

@ -6,7 +6,7 @@ require (
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1
github.com/Microsoft/hcsshim v0.10.0-rc.4 github.com/Microsoft/hcsshim v0.10.0-rc.4
github.com/Microsoft/hcsshim/test v0.0.0-20210408205431-da33ecd607e1 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/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/go-runc v1.0.0
github.com/containerd/ttrpc v1.1.1-0.20220420014843-944ef4a40df3 github.com/containerd/ttrpc v1.1.1-0.20220420014843-944ef4a40df3

View File

@ -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.3/go.mod h1:/ofk34relqNjSGyqPrmEULrO4Sc8LJhvJmWbUCUKqj8=
github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA= 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 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 h1:EzSABvwGkHxdwtZsNBWl8M3iNh+0lMJb/fmtyoSXlsc=
github.com/containerd/cgroups/v3 v3.0.0-20221112182753-e8802a182774/go.mod h1:/vtwk1VXrtoa5AaZLkypuOJgA/6DyPMZHJPGQNtlHnw= 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 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.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw=
github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ=

View File

@ -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 ### Attention
All static path should not include `/sys/fs/cgroup/` prefix, it should start with your own cgroups name All static path should not include `/sys/fs/cgroup/` prefix, it should start with your own cgroups name

View File

@ -43,7 +43,7 @@ type memoryThresholdEvent struct {
swap bool 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 // If swap is true, the event will be registered using memory.memsw.usage_in_bytes
func MemoryThresholdEvent(threshold uint64, swap bool) MemoryEvent { func MemoryThresholdEvent(threshold uint64, swap bool) MemoryEvent {
return &memoryThresholdEvent{ return &memoryThresholdEvent{
@ -83,7 +83,7 @@ type memoryPressureEvent struct {
hierarchy EventNotificationMode 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 { func MemoryPressureEvent(pressureLevel MemoryPressureLevel, hierarchy EventNotificationMode) MemoryEvent {
return &memoryPressureEvent{ return &memoryPressureEvent{
pressureLevel, pressureLevel,

View File

@ -42,6 +42,7 @@ import (
const ( const (
subtreeControl = "cgroup.subtree_control" subtreeControl = "cgroup.subtree_control"
controllersFile = "cgroup.controllers" controllersFile = "cgroup.controllers"
killFile = "cgroup.kill"
defaultCgroup2Path = "/sys/fs/cgroup" defaultCgroup2Path = "/sys/fs/cgroup"
defaultSlice = "system.slice" defaultSlice = "system.slice"
) )
@ -144,20 +145,11 @@ func (c *Value) write(path string, perm os.FileMode) error {
return ErrInvalidFormat return ErrInvalidFormat
} }
// Retry writes on EINTR; see: return os.WriteFile(
// https://github.com/golang/go/issues/38033 filepath.Join(path, c.filename),
for { data,
err := os.WriteFile( perm,
filepath.Join(path, c.filename), )
data,
perm,
)
if err == nil {
return nil
} else if !errors.Is(err, syscall.EINTR) {
return err
}
}
} }
func writeValues(path string, values []Value) error { func writeValues(path string, values []Value) error {
@ -202,7 +194,7 @@ type InitConfig struct {
type InitOpts func(c *InitConfig) error 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 { func WithMountpoint(path string) InitOpts {
return func(c *InitConfig) error { return func(c *InitConfig) error {
c.mountpoint = path c.mountpoint = path
@ -366,6 +358,86 @@ func (c *Manager) AddThread(tid uint64) error {
return writeValues(c.path, []Value{v}) 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 { func (c *Manager) Delete() error {
// kernel prevents cgroups with running process from being removed, check the tree is empty // kernel prevents cgroups with running process from being removed, check the tree is empty
processes, err := c.Procs(true) 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 // 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 slice. For example, when creating a slice called "my-group-112233.slice",
// systemd will create a hierarchy like this: // 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 { func getSystemdFullPath(slice, group string) string {
return filepath.Join(defaultCgroup2Path, dashesToPath(slice), dashesToPath(group)) return filepath.Join(defaultCgroup2Path, dashesToPath(slice), dashesToPath(group))
} }

View File

@ -26,12 +26,14 @@ import (
"strconv" "strconv"
"strings" "strings"
"time" "time"
"unsafe"
"github.com/containerd/cgroups/v3/cgroup2/stats" "github.com/containerd/cgroups/v3/cgroup2/stats"
"github.com/godbus/dbus/v5" "github.com/godbus/dbus/v5"
"github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-spec/specs-go"
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
"golang.org/x/sys/unix"
) )
const ( const (
@ -434,3 +436,11 @@ func readHugeTlbStats(path string) []*stats.HugeTlbStat {
} }
return usage 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
}

2
vendor/modules.txt vendored
View File

@ -92,7 +92,7 @@ github.com/containerd/btrfs
# github.com/containerd/cgroups v1.0.4 # github.com/containerd/cgroups v1.0.4
## explicit; go 1.17 ## explicit; go 1.17
github.com/containerd/cgroups/stats/v1 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 ## explicit; go 1.17
github.com/containerd/cgroups/v3 github.com/containerd/cgroups/v3
github.com/containerd/cgroups/v3/cgroup1 github.com/containerd/cgroups/v3/cgroup1