Skip to content

Commit 7f4398f

Browse files
committed
fix runc events error in cgroup v2
Signed-off-by: lifubang <[email protected]>
1 parent dbe44cb commit 7f4398f

File tree

5 files changed

+100
-1
lines changed

5 files changed

+100
-1
lines changed

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/coreos/go-systemd/v22 v22.0.0
1010
github.com/cyphar/filepath-securejoin v0.2.2
1111
github.com/docker/go-units v0.4.0
12+
github.com/fsnotify/fsnotify v1.4.9
1213
github.com/godbus/dbus/v5 v5.0.3
1314
github.com/golang/protobuf v1.3.5
1415
github.com/moby/sys/mountinfo v0.1.3

go.sum

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
1515
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
1616
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
1717
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
18+
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
19+
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
1820
github.com/godbus/dbus/v5 v5.0.3 h1:ZqHaoEF7TBzh4jzPmqVhE/5A1z9of6orkAe5uHoAeME=
1921
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
2022
github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
@@ -54,6 +56,7 @@ github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df h1:OviZH7qLw/7Zo
5456
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
5557
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
5658
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
59+
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
5760
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
5861
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
5962
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

libcontainer/container_linux.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,9 @@ func (c *linuxContainer) NotifyOOM() (<-chan struct{}, error) {
648648
if c.config.RootlessCgroups {
649649
logrus.Warn("getting OOM notifications may fail if you don't have the full access to cgroups")
650650
}
651+
if cgroups.IsCgroup2UnifiedMode() {
652+
return notifyOnOOMV2(c.cgroupManager.GetPaths())
653+
}
651654
return notifyOnOOM(c.cgroupManager.GetPaths())
652655
}
653656

libcontainer/notify_linux.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,4 @@ func notifyMemoryPressure(paths map[string]string, level PressureLevel) (<-chan
8787

8888
levelStr := []string{"low", "medium", "critical"}[level]
8989
return registerMemoryEvent(dir, "memory.pressure_level", levelStr)
90-
}
90+
}

libcontainer/notify_linux_v2.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
// +build linux
2+
3+
package libcontainer
4+
5+
import (
6+
"bufio"
7+
"fmt"
8+
"io"
9+
"os"
10+
"path/filepath"
11+
"strings"
12+
13+
"github.com/fsnotify/fsnotify"
14+
"github.com/sirupsen/logrus"
15+
)
16+
17+
func checkOOM(path string) (bool, error) {
18+
file, err := os.Open(path)
19+
defer file.Close()
20+
if err != nil {
21+
return false, err
22+
}
23+
buff := bufio.NewReader(file)
24+
for {
25+
line, err := buff.ReadString('\n')
26+
if err == io.EOF {
27+
break
28+
}
29+
arr := strings.Fields(line)
30+
if len(arr) == 2 && (arr[0] == "oom" || arr[0] == "oom_kill") && arr[1] == "1" {
31+
return true, nil
32+
}
33+
}
34+
return false, nil
35+
}
36+
37+
func registerMemoryEventV2(cgDir string, evName string, arg string) (<-chan struct{}, error) {
38+
eventControlPath := filepath.Join(cgDir, evName)
39+
watcher, err := fsnotify.NewWatcher()
40+
if err != nil {
41+
return nil, err
42+
}
43+
if err := watcher.Add(eventControlPath); err != nil {
44+
return nil, err
45+
}
46+
ch := make(chan struct{})
47+
go func() {
48+
defer func() {
49+
watcher.Close()
50+
close(ch)
51+
}()
52+
for {
53+
select {
54+
case event := <-watcher.Events:
55+
// When a cgroup is destroyed, an event is sent to eventfd.
56+
// So if the control path is gone, return instead of notifying.
57+
if _, err := os.Lstat(eventControlPath); os.IsNotExist(err) {
58+
return
59+
}
60+
if event.Op&fsnotify.Write > 0 {
61+
isOOM, err := checkOOM(eventControlPath)
62+
if err != nil {
63+
return
64+
}
65+
if isOOM {
66+
ch <- struct{}{}
67+
return
68+
}
69+
} else if event.Op&fsnotify.Remove > 0 {
70+
return
71+
}
72+
case err := <-watcher.Errors:
73+
if err != nil {
74+
logrus.Warn(err)
75+
return
76+
}
77+
}
78+
}
79+
}()
80+
return ch, nil
81+
}
82+
83+
// notifyOnOOMV2 returns channel on which you can expect event about OOM,
84+
// if process died without OOM this channel will be closed.
85+
func notifyOnOOMV2(paths map[string]string) (<-chan struct{}, error) {
86+
dir := paths[oomCgroupName]
87+
if dir == "" {
88+
return nil, fmt.Errorf("path %q missing", oomCgroupName)
89+
}
90+
91+
return registerMemoryEventV2(dir, "memory.events", "")
92+
}

0 commit comments

Comments
 (0)