Skip to content

Commit f159672

Browse files
authored
Fix proc limits (#340)
Linux limits are uint64, not int64[0]. "unlimited" is also defined as max uint64. [0]: https://github.com/torvalds/linux/blob/7c53f6b671f4aba70ff15e1b05148b10d58c2837/include/uapi/linux/resource.h#L48-L53 Signed-off-by: Brandon Bell <[email protected]>
1 parent 7b52fa5 commit f159672

File tree

3 files changed

+47
-43
lines changed

3 files changed

+47
-43
lines changed

Diff for: fixtures.ttar

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ Max core file size 0 unlimited bytes
111111
Max resident set unlimited unlimited bytes
112112
Max processes 62898 62898 processes
113113
Max open files 2048 4096 files
114-
Max locked memory 65536 65536 bytes
114+
Max locked memory 18446744073708503040 18446744073708503040 bytes
115115
Max address space 8589934592 unlimited bytes
116116
Max file locks unlimited unlimited locks
117117
Max pending signals 62898 62898 signals

Diff for: proc_limits.go

+43-39
Original file line numberDiff line numberDiff line change
@@ -26,55 +26,55 @@ import (
2626
// http://man7.org/linux/man-pages/man2/getrlimit.2.html.
2727
type ProcLimits struct {
2828
// CPU time limit in seconds.
29-
CPUTime int64
29+
CPUTime uint64
3030
// Maximum size of files that the process may create.
31-
FileSize int64
31+
FileSize uint64
3232
// Maximum size of the process's data segment (initialized data,
3333
// uninitialized data, and heap).
34-
DataSize int64
34+
DataSize uint64
3535
// Maximum size of the process stack in bytes.
36-
StackSize int64
36+
StackSize uint64
3737
// Maximum size of a core file.
38-
CoreFileSize int64
38+
CoreFileSize uint64
3939
// Limit of the process's resident set in pages.
40-
ResidentSet int64
40+
ResidentSet uint64
4141
// Maximum number of processes that can be created for the real user ID of
4242
// the calling process.
43-
Processes int64
43+
Processes uint64
4444
// Value one greater than the maximum file descriptor number that can be
4545
// opened by this process.
46-
OpenFiles int64
46+
OpenFiles uint64
4747
// Maximum number of bytes of memory that may be locked into RAM.
48-
LockedMemory int64
48+
LockedMemory uint64
4949
// Maximum size of the process's virtual memory address space in bytes.
50-
AddressSpace int64
50+
AddressSpace uint64
5151
// Limit on the combined number of flock(2) locks and fcntl(2) leases that
5252
// this process may establish.
53-
FileLocks int64
53+
FileLocks uint64
5454
// Limit of signals that may be queued for the real user ID of the calling
5555
// process.
56-
PendingSignals int64
56+
PendingSignals uint64
5757
// Limit on the number of bytes that can be allocated for POSIX message
5858
// queues for the real user ID of the calling process.
59-
MsqqueueSize int64
59+
MsqqueueSize uint64
6060
// Limit of the nice priority set using setpriority(2) or nice(2).
61-
NicePriority int64
61+
NicePriority uint64
6262
// Limit of the real-time priority set using sched_setscheduler(2) or
6363
// sched_setparam(2).
64-
RealtimePriority int64
64+
RealtimePriority uint64
6565
// Limit (in microseconds) on the amount of CPU time that a process
6666
// scheduled under a real-time scheduling policy may consume without making
6767
// a blocking system call.
68-
RealtimeTimeout int64
68+
RealtimeTimeout uint64
6969
}
7070

7171
const (
72-
limitsFields = 3
72+
limitsFields = 4
7373
limitsUnlimited = "unlimited"
7474
)
7575

7676
var (
77-
limitsDelimiter = regexp.MustCompile(" +")
77+
limitsMatch = regexp.MustCompile(`(Max \w+\s{0,1}?\w*\s{0,1}\w*)\s{2,}(\w+)\s+(\w+)`)
7878
)
7979

8080
// NewLimits returns the current soft limits of the process.
@@ -96,46 +96,50 @@ func (p Proc) Limits() (ProcLimits, error) {
9696
l = ProcLimits{}
9797
s = bufio.NewScanner(f)
9898
)
99+
100+
s.Scan() // Skip limits header
101+
99102
for s.Scan() {
100-
fields := limitsDelimiter.Split(s.Text(), limitsFields)
103+
//fields := limitsMatch.Split(s.Text(), limitsFields)
104+
fields := limitsMatch.FindStringSubmatch(s.Text())
101105
if len(fields) != limitsFields {
102106
return ProcLimits{}, fmt.Errorf(
103107
"couldn't parse %s line %s", f.Name(), s.Text())
104108
}
105109

106-
switch fields[0] {
110+
switch fields[1] {
107111
case "Max cpu time":
108-
l.CPUTime, err = parseInt(fields[1])
112+
l.CPUTime, err = parseUint(fields[2])
109113
case "Max file size":
110-
l.FileSize, err = parseInt(fields[1])
114+
l.FileSize, err = parseUint(fields[2])
111115
case "Max data size":
112-
l.DataSize, err = parseInt(fields[1])
116+
l.DataSize, err = parseUint(fields[2])
113117
case "Max stack size":
114-
l.StackSize, err = parseInt(fields[1])
118+
l.StackSize, err = parseUint(fields[2])
115119
case "Max core file size":
116-
l.CoreFileSize, err = parseInt(fields[1])
120+
l.CoreFileSize, err = parseUint(fields[2])
117121
case "Max resident set":
118-
l.ResidentSet, err = parseInt(fields[1])
122+
l.ResidentSet, err = parseUint(fields[2])
119123
case "Max processes":
120-
l.Processes, err = parseInt(fields[1])
124+
l.Processes, err = parseUint(fields[2])
121125
case "Max open files":
122-
l.OpenFiles, err = parseInt(fields[1])
126+
l.OpenFiles, err = parseUint(fields[2])
123127
case "Max locked memory":
124-
l.LockedMemory, err = parseInt(fields[1])
128+
l.LockedMemory, err = parseUint(fields[2])
125129
case "Max address space":
126-
l.AddressSpace, err = parseInt(fields[1])
130+
l.AddressSpace, err = parseUint(fields[2])
127131
case "Max file locks":
128-
l.FileLocks, err = parseInt(fields[1])
132+
l.FileLocks, err = parseUint(fields[2])
129133
case "Max pending signals":
130-
l.PendingSignals, err = parseInt(fields[1])
134+
l.PendingSignals, err = parseUint(fields[2])
131135
case "Max msgqueue size":
132-
l.MsqqueueSize, err = parseInt(fields[1])
136+
l.MsqqueueSize, err = parseUint(fields[2])
133137
case "Max nice priority":
134-
l.NicePriority, err = parseInt(fields[1])
138+
l.NicePriority, err = parseUint(fields[2])
135139
case "Max realtime priority":
136-
l.RealtimePriority, err = parseInt(fields[1])
140+
l.RealtimePriority, err = parseUint(fields[2])
137141
case "Max realtime timeout":
138-
l.RealtimeTimeout, err = parseInt(fields[1])
142+
l.RealtimeTimeout, err = parseUint(fields[2])
139143
}
140144
if err != nil {
141145
return ProcLimits{}, err
@@ -145,11 +149,11 @@ func (p Proc) Limits() (ProcLimits, error) {
145149
return l, s.Err()
146150
}
147151

148-
func parseInt(s string) (int64, error) {
152+
func parseUint(s string) (uint64, error) {
149153
if s == limitsUnlimited {
150-
return -1, nil
154+
return 18446744073709551615, nil
151155
}
152-
i, err := strconv.ParseInt(s, 10, 64)
156+
i, err := strconv.ParseUint(s, 10, 64)
153157
if err != nil {
154158
return 0, fmt.Errorf("couldn't parse value %s: %s", s, err)
155159
}

Diff for: proc_limits_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ func TestLimits(t *testing.T) {
2828

2929
for _, test := range []struct {
3030
name string
31-
want int64
32-
have int64
31+
want uint64
32+
have uint64
3333
}{
34-
{name: "cpu time", want: -1, have: l.CPUTime},
34+
{name: "cpu time", want: 18446744073709551615, have: l.CPUTime},
3535
{name: "open files", want: 2048, have: l.OpenFiles},
3636
{name: "msgqueue size", want: 819200, have: l.MsqqueueSize},
3737
{name: "nice priority", want: 0, have: l.NicePriority},

0 commit comments

Comments
 (0)