Skip to content

Commit 9814e5a

Browse files
author
xiejunqiao
committed
fix: correct memory limit detection for cgroup v1 and v2
- Fix memory limit detection logic for cgroup v1: treat 0x7FFFFFFFFFFFF000 (9223372036854771712) as unlimited. - Ensure cgroup v2 uses "max" as unlimited. - Update comments to English for better readability. - This ensures memory stress respects container memory limits correctly. Signed-off-by: xiejunqiao <[email protected]>
1 parent 6583ea9 commit 9814e5a

File tree

2 files changed

+77
-3
lines changed

2 files changed

+77
-3
lines changed

main.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ import (
2525
"time"
2626

2727
humanize "github.com/dustin/go-humanize"
28-
psutil "github.com/shirou/gopsutil/mem"
2928
)
3029

3130
var (
@@ -114,7 +113,11 @@ func main() {
114113
time.Sleep(time.Second)
115114
}
116115
} else {
117-
memInfo, _ := psutil.VirtualMemory()
116+
totalMem, err := getTotalMemory()
117+
if err != nil {
118+
fmt.Println("get total memory err:", err)
119+
return
120+
}
118121
var length uint64
119122

120123
if memSize[len(memSize)-1] != '%' {
@@ -129,7 +132,7 @@ func main() {
129132
if err != nil {
130133
fmt.Println(err)
131134
}
132-
length = uint64(float64(memInfo.Total) / 100.0 * percentage)
135+
length = uint64(float64(totalMem) / 100.0 * percentage)
133136
}
134137

135138
timeLine, err := time.ParseDuration(growthTime)

util.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"io/ioutil"
6+
"strconv"
7+
"strings"
8+
9+
psutil "github.com/shirou/gopsutil/mem"
10+
)
11+
12+
const (
13+
cgroupV2Path = "/sys/fs/cgroup/memory.max"
14+
cgroupV1Path = "/sys/fs/cgroup/memory/memory.limit_in_bytes"
15+
cgroupNoLimitV1 = 0x7FFFFFFFFFFFF000
16+
)
17+
18+
// Read file content and parse as uint64
19+
func readUintFromFile(path string) (uint64, error) {
20+
data, err := ioutil.ReadFile(path)
21+
if err != nil {
22+
return 0, err
23+
}
24+
content := strings.TrimSpace(string(data))
25+
return strconv.ParseUint(content, 10, 64)
26+
}
27+
28+
// Check cgroup v2 memory limit
29+
func getCgroupV2Limit() (uint64, error) {
30+
data, err := ioutil.ReadFile(cgroupV2Path)
31+
if err != nil {
32+
return 0, err
33+
}
34+
content := strings.TrimSpace(string(data))
35+
if content == "max" {
36+
return 0, fmt.Errorf("cgroup v2: no memory limit set")
37+
}
38+
limit, err := strconv.ParseUint(content, 10, 64)
39+
if err != nil || limit == 0 {
40+
return 0, fmt.Errorf("cgroup v2: invalid memory limit")
41+
}
42+
return limit, nil
43+
}
44+
45+
// Check cgroup v1 memory limit
46+
func getCgroupV1Limit() (uint64, error) {
47+
limit, err := readUintFromFile(cgroupV1Path)
48+
if err != nil {
49+
return 0, err
50+
}
51+
// 0 or cgroup's "infinity" value means no limit
52+
if limit == 0 || limit >= cgroupNoLimitV1 {
53+
return 0, fmt.Errorf("cgroup v1: no memory limit set")
54+
}
55+
return limit, nil
56+
}
57+
58+
// Get total memory, prefer cgroup v2 -> cgroup v1 -> host
59+
func getTotalMemory() (uint64, error) {
60+
if limit, err := getCgroupV2Limit(); err == nil {
61+
return limit, nil
62+
}
63+
if limit, err := getCgroupV1Limit(); err == nil {
64+
return limit, nil
65+
}
66+
mem, err := psutil.VirtualMemory()
67+
if err != nil {
68+
return 0, fmt.Errorf("failed to get system memory: %v", err)
69+
}
70+
return mem.Total, nil
71+
}

0 commit comments

Comments
 (0)