Codebase list golang-procfs / f159672
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 <bbell@invoca.com> Brandon Bell authored 3 years ago GitHub committed 3 years ago
3 changed file(s) with 47 addition(s) and 43 deletion(s). Raw diff Collapse all Expand all
110110 Max resident set unlimited unlimited bytes
111111 Max processes 62898 62898 processes
112112 Max open files 2048 4096 files
113 Max locked memory 65536 65536 bytes
113 Max locked memory 18446744073708503040 18446744073708503040 bytes
114114 Max address space 8589934592 unlimited bytes
115115 Max file locks unlimited unlimited locks
116116 Max pending signals 62898 62898 signals
2525 // http://man7.org/linux/man-pages/man2/getrlimit.2.html.
2626 type ProcLimits struct {
2727 // CPU time limit in seconds.
28 CPUTime int64
28 CPUTime uint64
2929 // Maximum size of files that the process may create.
30 FileSize int64
30 FileSize uint64
3131 // Maximum size of the process's data segment (initialized data,
3232 // uninitialized data, and heap).
33 DataSize int64
33 DataSize uint64
3434 // Maximum size of the process stack in bytes.
35 StackSize int64
35 StackSize uint64
3636 // Maximum size of a core file.
37 CoreFileSize int64
37 CoreFileSize uint64
3838 // Limit of the process's resident set in pages.
39 ResidentSet int64
39 ResidentSet uint64
4040 // Maximum number of processes that can be created for the real user ID of
4141 // the calling process.
42 Processes int64
42 Processes uint64
4343 // Value one greater than the maximum file descriptor number that can be
4444 // opened by this process.
45 OpenFiles int64
45 OpenFiles uint64
4646 // Maximum number of bytes of memory that may be locked into RAM.
47 LockedMemory int64
47 LockedMemory uint64
4848 // Maximum size of the process's virtual memory address space in bytes.
49 AddressSpace int64
49 AddressSpace uint64
5050 // Limit on the combined number of flock(2) locks and fcntl(2) leases that
5151 // this process may establish.
52 FileLocks int64
52 FileLocks uint64
5353 // Limit of signals that may be queued for the real user ID of the calling
5454 // process.
55 PendingSignals int64
55 PendingSignals uint64
5656 // Limit on the number of bytes that can be allocated for POSIX message
5757 // queues for the real user ID of the calling process.
58 MsqqueueSize int64
58 MsqqueueSize uint64
5959 // Limit of the nice priority set using setpriority(2) or nice(2).
60 NicePriority int64
60 NicePriority uint64
6161 // Limit of the real-time priority set using sched_setscheduler(2) or
6262 // sched_setparam(2).
63 RealtimePriority int64
63 RealtimePriority uint64
6464 // Limit (in microseconds) on the amount of CPU time that a process
6565 // scheduled under a real-time scheduling policy may consume without making
6666 // a blocking system call.
67 RealtimeTimeout int64
67 RealtimeTimeout uint64
6868 }
6969
7070 const (
71 limitsFields = 3
71 limitsFields = 4
7272 limitsUnlimited = "unlimited"
7373 )
7474
7575 var (
76 limitsDelimiter = regexp.MustCompile(" +")
76 limitsMatch = regexp.MustCompile(`(Max \w+\s{0,1}?\w*\s{0,1}\w*)\s{2,}(\w+)\s+(\w+)`)
7777 )
7878
7979 // NewLimits returns the current soft limits of the process.
9595 l = ProcLimits{}
9696 s = bufio.NewScanner(f)
9797 )
98
99 s.Scan() // Skip limits header
100
98101 for s.Scan() {
99 fields := limitsDelimiter.Split(s.Text(), limitsFields)
102 //fields := limitsMatch.Split(s.Text(), limitsFields)
103 fields := limitsMatch.FindStringSubmatch(s.Text())
100104 if len(fields) != limitsFields {
101105 return ProcLimits{}, fmt.Errorf(
102106 "couldn't parse %s line %s", f.Name(), s.Text())
103107 }
104108
105 switch fields[0] {
109 switch fields[1] {
106110 case "Max cpu time":
107 l.CPUTime, err = parseInt(fields[1])
111 l.CPUTime, err = parseUint(fields[2])
108112 case "Max file size":
109 l.FileSize, err = parseInt(fields[1])
113 l.FileSize, err = parseUint(fields[2])
110114 case "Max data size":
111 l.DataSize, err = parseInt(fields[1])
115 l.DataSize, err = parseUint(fields[2])
112116 case "Max stack size":
113 l.StackSize, err = parseInt(fields[1])
117 l.StackSize, err = parseUint(fields[2])
114118 case "Max core file size":
115 l.CoreFileSize, err = parseInt(fields[1])
119 l.CoreFileSize, err = parseUint(fields[2])
116120 case "Max resident set":
117 l.ResidentSet, err = parseInt(fields[1])
121 l.ResidentSet, err = parseUint(fields[2])
118122 case "Max processes":
119 l.Processes, err = parseInt(fields[1])
123 l.Processes, err = parseUint(fields[2])
120124 case "Max open files":
121 l.OpenFiles, err = parseInt(fields[1])
125 l.OpenFiles, err = parseUint(fields[2])
122126 case "Max locked memory":
123 l.LockedMemory, err = parseInt(fields[1])
127 l.LockedMemory, err = parseUint(fields[2])
124128 case "Max address space":
125 l.AddressSpace, err = parseInt(fields[1])
129 l.AddressSpace, err = parseUint(fields[2])
126130 case "Max file locks":
127 l.FileLocks, err = parseInt(fields[1])
131 l.FileLocks, err = parseUint(fields[2])
128132 case "Max pending signals":
129 l.PendingSignals, err = parseInt(fields[1])
133 l.PendingSignals, err = parseUint(fields[2])
130134 case "Max msgqueue size":
131 l.MsqqueueSize, err = parseInt(fields[1])
135 l.MsqqueueSize, err = parseUint(fields[2])
132136 case "Max nice priority":
133 l.NicePriority, err = parseInt(fields[1])
137 l.NicePriority, err = parseUint(fields[2])
134138 case "Max realtime priority":
135 l.RealtimePriority, err = parseInt(fields[1])
139 l.RealtimePriority, err = parseUint(fields[2])
136140 case "Max realtime timeout":
137 l.RealtimeTimeout, err = parseInt(fields[1])
141 l.RealtimeTimeout, err = parseUint(fields[2])
138142 }
139143 if err != nil {
140144 return ProcLimits{}, err
144148 return l, s.Err()
145149 }
146150
147 func parseInt(s string) (int64, error) {
151 func parseUint(s string) (uint64, error) {
148152 if s == limitsUnlimited {
149 return -1, nil
153 return 18446744073709551615, nil
150154 }
151 i, err := strconv.ParseInt(s, 10, 64)
155 i, err := strconv.ParseUint(s, 10, 64)
152156 if err != nil {
153157 return 0, fmt.Errorf("couldn't parse value %s: %s", s, err)
154158 }
2727
2828 for _, test := range []struct {
2929 name string
30 want int64
31 have int64
30 want uint64
31 have uint64
3232 }{
33 {name: "cpu time", want: -1, have: l.CPUTime},
33 {name: "cpu time", want: 18446744073709551615, have: l.CPUTime},
3434 {name: "open files", want: 2048, have: l.OpenFiles},
3535 {name: "msgqueue size", want: 819200, have: l.MsqqueueSize},
3636 {name: "nice priority", want: 0, have: l.NicePriority},