1// Copyright 2018 The Prometheus Authors 2// Licensed under the Apache License, Version 2.0 (the "License"); 3// you may not use this file except in compliance with the License. 4// You may obtain a copy of the License at 5// 6// http://www.apache.org/licenses/LICENSE-2.0 7// 8// Unless required by applicable law or agreed to in writing, software 9// distributed under the License is distributed on an "AS IS" BASIS, 10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11// See the License for the specific language governing permissions and 12// limitations under the License. 13 14package procfs 15 16import ( 17 "bufio" 18 "fmt" 19 "os" 20 "regexp" 21 "strconv" 22) 23 24// ProcLimits represents the soft limits for each of the process's resource 25// limits. For more information see getrlimit(2): 26// http://man7.org/linux/man-pages/man2/getrlimit.2.html. 27type ProcLimits struct { 28 // CPU time limit in seconds. 29 CPUTime uint64 30 // Maximum size of files that the process may create. 31 FileSize uint64 32 // Maximum size of the process's data segment (initialized data, 33 // uninitialized data, and heap). 34 DataSize uint64 35 // Maximum size of the process stack in bytes. 36 StackSize uint64 37 // Maximum size of a core file. 38 CoreFileSize uint64 39 // Limit of the process's resident set in pages. 40 ResidentSet uint64 41 // Maximum number of processes that can be created for the real user ID of 42 // the calling process. 43 Processes uint64 44 // Value one greater than the maximum file descriptor number that can be 45 // opened by this process. 46 OpenFiles uint64 47 // Maximum number of bytes of memory that may be locked into RAM. 48 LockedMemory uint64 49 // Maximum size of the process's virtual memory address space in bytes. 50 AddressSpace uint64 51 // Limit on the combined number of flock(2) locks and fcntl(2) leases that 52 // this process may establish. 53 FileLocks uint64 54 // Limit of signals that may be queued for the real user ID of the calling 55 // process. 56 PendingSignals uint64 57 // Limit on the number of bytes that can be allocated for POSIX message 58 // queues for the real user ID of the calling process. 59 MsqqueueSize uint64 60 // Limit of the nice priority set using setpriority(2) or nice(2). 61 NicePriority uint64 62 // Limit of the real-time priority set using sched_setscheduler(2) or 63 // sched_setparam(2). 64 RealtimePriority uint64 65 // Limit (in microseconds) on the amount of CPU time that a process 66 // scheduled under a real-time scheduling policy may consume without making 67 // a blocking system call. 68 RealtimeTimeout uint64 69} 70 71const ( 72 limitsFields = 4 73 limitsUnlimited = "unlimited" 74) 75 76var ( 77 limitsMatch = regexp.MustCompile(`(Max \w+\s{0,1}?\w*\s{0,1}\w*)\s{2,}(\w+)\s+(\w+)`) 78) 79 80// NewLimits returns the current soft limits of the process. 81// 82// Deprecated: use p.Limits() instead 83func (p Proc) NewLimits() (ProcLimits, error) { 84 return p.Limits() 85} 86 87// Limits returns the current soft limits of the process. 88func (p Proc) Limits() (ProcLimits, error) { 89 f, err := os.Open(p.path("limits")) 90 if err != nil { 91 return ProcLimits{}, err 92 } 93 defer f.Close() 94 95 var ( 96 l = ProcLimits{} 97 s = bufio.NewScanner(f) 98 ) 99 100 s.Scan() // Skip limits header 101 102 for s.Scan() { 103 //fields := limitsMatch.Split(s.Text(), limitsFields) 104 fields := limitsMatch.FindStringSubmatch(s.Text()) 105 if len(fields) != limitsFields { 106 return ProcLimits{}, fmt.Errorf("couldn't parse %q line %q", f.Name(), s.Text()) 107 } 108 109 switch fields[1] { 110 case "Max cpu time": 111 l.CPUTime, err = parseUint(fields[2]) 112 case "Max file size": 113 l.FileSize, err = parseUint(fields[2]) 114 case "Max data size": 115 l.DataSize, err = parseUint(fields[2]) 116 case "Max stack size": 117 l.StackSize, err = parseUint(fields[2]) 118 case "Max core file size": 119 l.CoreFileSize, err = parseUint(fields[2]) 120 case "Max resident set": 121 l.ResidentSet, err = parseUint(fields[2]) 122 case "Max processes": 123 l.Processes, err = parseUint(fields[2]) 124 case "Max open files": 125 l.OpenFiles, err = parseUint(fields[2]) 126 case "Max locked memory": 127 l.LockedMemory, err = parseUint(fields[2]) 128 case "Max address space": 129 l.AddressSpace, err = parseUint(fields[2]) 130 case "Max file locks": 131 l.FileLocks, err = parseUint(fields[2]) 132 case "Max pending signals": 133 l.PendingSignals, err = parseUint(fields[2]) 134 case "Max msgqueue size": 135 l.MsqqueueSize, err = parseUint(fields[2]) 136 case "Max nice priority": 137 l.NicePriority, err = parseUint(fields[2]) 138 case "Max realtime priority": 139 l.RealtimePriority, err = parseUint(fields[2]) 140 case "Max realtime timeout": 141 l.RealtimeTimeout, err = parseUint(fields[2]) 142 } 143 if err != nil { 144 return ProcLimits{}, err 145 } 146 } 147 148 return l, s.Err() 149} 150 151func parseUint(s string) (uint64, error) { 152 if s == limitsUnlimited { 153 return 18446744073709551615, nil 154 } 155 i, err := strconv.ParseUint(s, 10, 64) 156 if err != nil { 157 return 0, fmt.Errorf("couldn't parse value %q: %w", s, err) 158 } 159 return i, nil 160} 161