From 2ec3e052ffb91f89ea750365af6c5df05a4d10f6 Mon Sep 17 00:00:00 2001 From: Vyacheslav Kulakov Date: Thu, 29 Jul 2021 14:36:28 +0300 Subject: [PATCH 1/4] Fix data types for CUTime and CSTime stat fields #403 These two stat fields (CUTime and CSTime) in the /proc/[pid]/stat file should have the signed long data type according to the documentation. But currently in the code their data type is just unsigned int. This commit fixes it and adds more tests. See for details: * https://man7.org/linux/man-pages/man5/proc.5.html * https://man7.org/linux/man-pages/man3/scanf.3.html Signed-off-by: Vyacheslav Kulakov --- fixtures.ttar | 2 +- proc_stat.go | 43 ++++++++++++++++++++++++------------------- proc_stat_test.go | 19 +++++++++++++++++-- 3 files changed, 42 insertions(+), 22 deletions(-) diff --git a/fixtures.ttar b/fixtures.ttar index e7d35069c..ce74c4f3a 100644 --- a/fixtures.ttar +++ b/fixtures.ttar @@ -589,7 +589,7 @@ SymlinkTo: /does/not/exist # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26232/stat Lines: 1 -33 (ata_sff) S 2 0 0 0 -1 69238880 0 0 0 0 0 0 0 0 0 -20 1 0 5 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 18446744073709551615 0 0 17 1 0 0 0 0 0 0 0 0 0 0 0 0 0 +33 (ata_sff) S 2 0 0 0 -1 69238880 0 0 0 0 0 0 -9223372036854775808 9223372036854775807 0 -20 1 0 5 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 18446744073709551615 0 0 -9223372036854775808 9223372036854775807 0 0 0 0 0 0 0 0 0 0 0 0 0 Mode: 644 # ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Path: fixtures/proc/26232/wchan diff --git a/proc_stat.go b/proc_stat.go index 8c7b6e80a..d01a9e191 100644 --- a/proc_stat.go +++ b/proc_stat.go @@ -81,10 +81,10 @@ type ProcStat struct { STime uint // Amount of time that this process's waited-for children have been // scheduled in user mode, measured in clock ticks. - CUTime uint + CUTime int // Amount of time that this process's waited-for children have been // scheduled in kernel mode, measured in clock ticks. - CSTime uint + CSTime int // For processes running a real-time scheduling policy, this is the negated // scheduling priority, minus one. Priority int @@ -128,8 +128,8 @@ func (p Proc) Stat() (ProcStat, error) { } var ( - ignoreInt64 int64 - ignoreUint64 uint64 + ignoreInt int + ignoreUint uint s = ProcStat{PID: p.PID, proc: p.fs} l = bytes.Index(data, []byte("(")) @@ -141,6 +141,11 @@ func (p Proc) Stat() (ProcStat, error) { } s.Comm = string(data[l+1 : r]) + + // Check the following resources for the details about the particular stat + // fields and their data types: + // * https://man7.org/linux/man-pages/man5/proc.5.html + // * https://man7.org/linux/man-pages/man3/scanf.3.html _, err = fmt.Fscan( bytes.NewBuffer(data[r+2:]), &s.State, @@ -161,25 +166,25 @@ func (p Proc) Stat() (ProcStat, error) { &s.Priority, &s.Nice, &s.NumThreads, - &ignoreInt64, + &ignoreInt, &s.Starttime, &s.VSize, &s.RSS, &s.RSSLimit, - &ignoreUint64, - &ignoreUint64, - &ignoreUint64, - &ignoreUint64, - &ignoreUint64, - &ignoreUint64, - &ignoreUint64, - &ignoreUint64, - &ignoreUint64, - &ignoreUint64, - &ignoreUint64, - &ignoreUint64, - &ignoreInt64, - &ignoreInt64, + &ignoreUint, + &ignoreUint, + &ignoreUint, + &ignoreUint, + &ignoreUint, + &ignoreUint, + &ignoreUint, + &ignoreUint, + &ignoreUint, + &ignoreUint, + &ignoreUint, + &ignoreUint, + &ignoreInt, + &ignoreInt, &s.RTPriority, &s.Policy, &s.DelayAcctBlkIOTicks, diff --git a/proc_stat_test.go b/proc_stat_test.go index 53491050e..c8d219088 100644 --- a/proc_stat_test.go +++ b/proc_stat_test.go @@ -14,6 +14,7 @@ package procfs import ( + "math" "os" "testing" ) @@ -76,16 +77,30 @@ func TestProcStat(t *testing.T) { } } -func TestProcStatIgnored(t *testing.T) { +func TestProcStatLimits(t *testing.T) { p, err := getProcFixtures(t).Proc(26232) if err != nil { t.Fatal(err) } - _, err = p.Stat() + s, err := p.Stat() if err != nil { t.Errorf("want not error, have %s", err) } + + // max values of stat int fields + for _, test := range []struct { + name string + want int + have int + }{ + {name: "user time in clock ticks", want: math.MinInt64, have: s.CUTime}, + {name: "system time in clock ticks", want: math.MaxInt64, have: s.CSTime}, + } { + if test.want != test.have { + t.Errorf("want %s %d, have %d", test.name, test.want, test.have) + } + } } func TestProcStatComm(t *testing.T) { From 850087ebb56ced94be8335526fa2fcd81316cda0 Mon Sep 17 00:00:00 2001 From: Vyacheslav Kulakov Date: Thu, 29 Jul 2021 14:44:27 +0300 Subject: [PATCH 2/4] Fix test names Signed-off-by: Vyacheslav Kulakov --- proc_stat_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proc_stat_test.go b/proc_stat_test.go index c8d219088..e49a0afc0 100644 --- a/proc_stat_test.go +++ b/proc_stat_test.go @@ -94,8 +94,8 @@ func TestProcStatLimits(t *testing.T) { want int have int }{ - {name: "user time in clock ticks", want: math.MinInt64, have: s.CUTime}, - {name: "system time in clock ticks", want: math.MaxInt64, have: s.CSTime}, + {name: "waited-for children user time", want: math.MinInt64, have: s.CUTime}, + {name: "waited-for children system time", want: math.MaxInt64, have: s.CSTime}, } { if test.want != test.have { t.Errorf("want %s %d, have %d", test.name, test.want, test.have) From 6315b9c47418b818be1d25a97d0024bc2d4d8ae3 Mon Sep 17 00:00:00 2001 From: Vyacheslav Kulakov Date: Thu, 29 Jul 2021 14:49:45 +0300 Subject: [PATCH 3/4] Sign the commit Signed-off-by: Vyacheslav Kulakov kulakov.home@gmail.com Signed-off-by: Vyacheslav Kulakov --- proc_stat_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proc_stat_test.go b/proc_stat_test.go index e49a0afc0..8be1e1318 100644 --- a/proc_stat_test.go +++ b/proc_stat_test.go @@ -94,8 +94,8 @@ func TestProcStatLimits(t *testing.T) { want int have int }{ - {name: "waited-for children user time", want: math.MinInt64, have: s.CUTime}, - {name: "waited-for children system time", want: math.MaxInt64, have: s.CSTime}, + {name: "waited for children user time", want: math.MinInt64, have: s.CUTime}, + {name: "waited for children system time", want: math.MaxInt64, have: s.CSTime}, } { if test.want != test.have { t.Errorf("want %s %d, have %d", test.name, test.want, test.have) From f892ce9ee8e8c67d6566d85076cd97816e46ebee Mon Sep 17 00:00:00 2001 From: Vyacheslav Kulakov Date: Mon, 30 Aug 2021 18:58:13 +0300 Subject: [PATCH 4/4] Revert types for the ignored fields Signed-off-by: Vyacheslav Kulakov kulakov.home@gmail.com Signed-off-by: Vyacheslav Kulakov --- proc_stat.go | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/proc_stat.go b/proc_stat.go index d01a9e191..ad03d85ef 100644 --- a/proc_stat.go +++ b/proc_stat.go @@ -128,8 +128,8 @@ func (p Proc) Stat() (ProcStat, error) { } var ( - ignoreInt int - ignoreUint uint + ignoreInt64 int64 + ignoreUint64 uint64 s = ProcStat{PID: p.PID, proc: p.fs} l = bytes.Index(data, []byte("(")) @@ -166,25 +166,25 @@ func (p Proc) Stat() (ProcStat, error) { &s.Priority, &s.Nice, &s.NumThreads, - &ignoreInt, + &ignoreInt64, &s.Starttime, &s.VSize, &s.RSS, &s.RSSLimit, - &ignoreUint, - &ignoreUint, - &ignoreUint, - &ignoreUint, - &ignoreUint, - &ignoreUint, - &ignoreUint, - &ignoreUint, - &ignoreUint, - &ignoreUint, - &ignoreUint, - &ignoreUint, - &ignoreInt, - &ignoreInt, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreUint64, + &ignoreInt64, + &ignoreInt64, &s.RTPriority, &s.Policy, &s.DelayAcctBlkIOTicks,