mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-11 14:13:58 +08:00
741acec5b7
Commitb2f8a74d"clothed" the naked return as inflicted by gofumpt v0.9.0. Since gofumpt v0.9.2 this rule was moved to "extra" category, not enabled by default. The only other "extra" rule is to group adjacent parameters with the same type, which also makes sense. Enable gofumpt "extra" rules, and reformat the code accordingly. Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com> (cherry picked from commit67840cce4b) Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
85 lines
1.9 KiB
Go
85 lines
1.9 KiB
Go
package libcontainer
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
type PressureLevel uint
|
|
|
|
const (
|
|
LowPressure PressureLevel = iota
|
|
MediumPressure
|
|
CriticalPressure
|
|
)
|
|
|
|
func registerMemoryEvent(cgDir, evName, arg string) (<-chan struct{}, error) {
|
|
evFile, err := os.Open(filepath.Join(cgDir, evName))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
fd, err := unix.Eventfd(0, unix.EFD_CLOEXEC)
|
|
if err != nil {
|
|
evFile.Close()
|
|
return nil, err
|
|
}
|
|
|
|
eventfd := os.NewFile(uintptr(fd), "eventfd")
|
|
|
|
eventControlPath := filepath.Join(cgDir, "cgroup.event_control")
|
|
data := fmt.Sprintf("%d %d %s", eventfd.Fd(), evFile.Fd(), arg)
|
|
if err := os.WriteFile(eventControlPath, []byte(data), 0o700); err != nil {
|
|
eventfd.Close()
|
|
evFile.Close()
|
|
return nil, err
|
|
}
|
|
ch := make(chan struct{})
|
|
go func() {
|
|
defer func() {
|
|
eventfd.Close()
|
|
evFile.Close()
|
|
close(ch)
|
|
}()
|
|
buf := make([]byte, 8)
|
|
for {
|
|
if _, err := eventfd.Read(buf); err != nil {
|
|
return
|
|
}
|
|
// When a cgroup is destroyed, an event is sent to eventfd.
|
|
// So if the control path is gone, return instead of notifying.
|
|
if _, err := os.Lstat(eventControlPath); os.IsNotExist(err) {
|
|
return
|
|
}
|
|
ch <- struct{}{}
|
|
}
|
|
}()
|
|
return ch, nil
|
|
}
|
|
|
|
// notifyOnOOM returns channel on which you can expect event about OOM,
|
|
// if process died without OOM this channel will be closed.
|
|
func notifyOnOOM(dir string) (<-chan struct{}, error) {
|
|
if dir == "" {
|
|
return nil, errors.New("memory controller missing")
|
|
}
|
|
|
|
return registerMemoryEvent(dir, "memory.oom_control", "")
|
|
}
|
|
|
|
func notifyMemoryPressure(dir string, level PressureLevel) (<-chan struct{}, error) {
|
|
if dir == "" {
|
|
return nil, errors.New("memory controller missing")
|
|
}
|
|
|
|
if level > CriticalPressure {
|
|
return nil, fmt.Errorf("invalid pressure level %d", level)
|
|
}
|
|
|
|
levelStr := []string{"low", "medium", "critical"}[level]
|
|
return registerMemoryEvent(dir, "memory.pressure_level", levelStr)
|
|
}
|