Merge pull request #8027 from AkihiroSuda/containerd-cgroups-v3
go.mod: github.com/containerd/cgroups/v3 v3.0.0
This commit is contained in:
13
vendor/github.com/containerd/cgroups/v3/README.md
generated
vendored
13
vendor/github.com/containerd/cgroups/v3/README.md
generated
vendored
@@ -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
|
||||
|
||||
4
vendor/github.com/containerd/cgroups/v3/cgroup1/memory.go
generated
vendored
4
vendor/github.com/containerd/cgroups/v3/cgroup1/memory.go
generated
vendored
@@ -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,
|
||||
|
||||
105
vendor/github.com/containerd/cgroups/v3/cgroup2/manager.go
generated
vendored
105
vendor/github.com/containerd/cgroups/v3/cgroup2/manager.go
generated
vendored
@@ -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))
|
||||
}
|
||||
|
||||
10
vendor/github.com/containerd/cgroups/v3/cgroup2/utils.go
generated
vendored
10
vendor/github.com/containerd/cgroups/v3/cgroup2/utils.go
generated
vendored
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user