Added limit constants. Implemented function to parse process limits from /proc.

pull/296/head
Vyacheslav Kuznetsov 8 years ago committed by Vyacheslav Kuznetsov
parent 93564b3142
commit 4de4e17f06

@ -60,6 +60,25 @@ type NumCtxSwitchesStat struct {
Involuntary int64 `json:"involuntary"`
}
const (
RLIMIT_CPU int32 = 0
RLIMIT_FSIZE int32 = 1
RLIMIT_DATA int32 = 2
RLIMIT_STACK int32 = 3
RLIMIT_CORE int32 = 4
RLIMIT_RSS int32 = 5
RLIMIT_NPROC int32 = 6
RLIMIT_NOFILE int32 = 7
RLIMIT_MEMLOCK int32 = 8
RLIMIT_AS int32 = 9
RLIMIT_LOCKS int32 = 10
RLIMIT_SIGPENDING int32 = 11
RLIMIT_MSGQUEUE int32 = 12
RLIMIT_NICE int32 = 13
RLIMIT_RTPRIO int32 = 14
RLIMIT_RTTIME int32 = 15
)
func (p Process) String() string {
s, _ := json.Marshal(p)
return string(s)

@ -14,10 +14,12 @@ import (
"strings"
"syscall"
"bufio"
"github.com/shirou/gopsutil/cpu"
"github.com/shirou/gopsutil/host"
"github.com/shirou/gopsutil/internal/common"
"github.com/shirou/gopsutil/net"
"math"
)
var (
@ -198,7 +200,7 @@ func (p *Process) IOnice() (int32, error) {
// Rlimit returns Resource Limits.
func (p *Process) Rlimit() ([]RlimitStat, error) {
return nil, common.ErrNotImplementedError
return p.fillFromLimits()
}
// IOCounters returns IO Counters.
@ -407,6 +409,111 @@ func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) {
** Internal functions
**/
func limitToInt(val string) (int32, error) {
if val == "unlimited" {
return math.MaxInt32, nil
} else {
res, err := strconv.ParseInt(val, 10, 32)
if err != nil {
return 0, err
}
return int32(res), nil
}
}
// Get num_fds from /proc/(pid)/limits
func (p *Process) fillFromLimits() ([]RlimitStat, error) {
pid := p.Pid
limitsFile := common.HostProc(strconv.Itoa(int(pid)), "limits")
d, err := os.Open(limitsFile)
if err != nil {
return nil, err
}
defer d.Close()
var limitStats []RlimitStat
limitsScanner := bufio.NewScanner(d)
for limitsScanner.Scan() {
var statItem RlimitStat
str := strings.Fields(limitsScanner.Text())
// Remove the header line
if strings.Contains(str[len(str)-1], "Units") {
continue
}
// Assert that last item is a Hard limit
statItem.Hard, err = limitToInt(str[len(str)-1])
if err != nil {
// On error remove last item an try once again since it can be unit or header line
str = str[:len(str)-1]
statItem.Hard, err = limitToInt(str[len(str)-1])
if err != nil {
return nil, err
}
}
// Remove last item from string
str = str[:len(str)-1]
//Now last item is a Soft limit
statItem.Soft, err = limitToInt(str[len(str)-1])
if err != nil {
return nil, err
}
// Remove last item from string
str = str[:len(str)-1]
//The rest is a stats name
resourceName := strings.Join(str, " ")
switch resourceName {
case "Max cpu time":
statItem.Resource = RLIMIT_CPU
case "Max file size":
statItem.Resource = RLIMIT_FSIZE
case "Max data size":
statItem.Resource = RLIMIT_DATA
case "Max stack size":
statItem.Resource = RLIMIT_STACK
case "Max core file size":
statItem.Resource = RLIMIT_CORE
case "Max resident set":
statItem.Resource = RLIMIT_RSS
case "Max processes":
statItem.Resource = RLIMIT_NPROC
case "Max open files":
statItem.Resource = RLIMIT_NOFILE
case "Max locked memory":
statItem.Resource = RLIMIT_MEMLOCK
case "Max address space":
statItem.Resource = RLIMIT_AS
case "Max file locks":
statItem.Resource = RLIMIT_LOCKS
case "Max pending signals":
statItem.Resource = RLIMIT_SIGPENDING
case "Max msgqueue size":
statItem.Resource = RLIMIT_MSGQUEUE
case "Max nice priority":
statItem.Resource = RLIMIT_NICE
case "Max realtime priority":
statItem.Resource = RLIMIT_RTPRIO
case "Max realtime timeout":
statItem.Resource = RLIMIT_RTTIME
default:
continue
}
limitStats = append(limitStats, statItem)
}
if err := limitsScanner.Err(); err != nil {
return nil, err
}
return limitStats, nil
}
// Get num_fds from /proc/(pid)/fd
func (p *Process) fillFromfd() (int32, []*OpenFilesStat, error) {
pid := p.Pid

Loading…
Cancel
Save