Fix issue in `GetProcessStartTime`
This fix tries to address the issue raised in docker: https://github.com/docker/docker/issues/27540 The issue was that `GetProcessStartTime` use space `" "` to split the `/proc/[pid]/stat` and take the `22`th value. However, the `2`th value is inside `(` and `)`, and could contain space. The following are two examples: ``` ubuntu@ubuntu:~/runc$ cat /proc/90286/stat 90286 (bash) S 90271 90286 90286 34818 90286 4194560 1412 1130576 4 0 2 1 2334 438 20 0 1 0 3093098 20733952 823 18446744073709551615 1 1 0 0 0 0 0 3670020 1266777851 0 0 0 17 1 0 0 0 0 0 0 0 0 0 0 0 0 0 ubuntu@ubuntu:~/runc$ cat /proc/89653/stat 89653 (gunicorn: maste) S 89630 89653 89653 0 -1 4194560 29689 28896 0 3 146 32 76 19 20 0 1 0 2971844 52965376 3920 18446744073709551615 1 1 0 0 0 0 0 16781312 137447943 0 0 0 17 1 0 0 0 0 0 0 0 0 0 0 0 0 0 ``` This fix fixes this issue by removing the prefix before `)`, then finding the `20`th value (instead of `22`th value). Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This commit is contained in:
parent
2a5001c1bc
commit
a83f5bac28
|
@ -14,8 +14,10 @@ func GetProcessStartTime(pid int) (string, error) {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return parseStartTime(string(data))
|
||||
}
|
||||
|
||||
parts := strings.Split(string(data), " ")
|
||||
func parseStartTime(stat string) (string, error) {
|
||||
// the starttime is located at pos 22
|
||||
// from the man page
|
||||
//
|
||||
|
@ -23,5 +25,19 @@ func GetProcessStartTime(pid int) (string, error) {
|
|||
// (22) The time the process started after system boot. In kernels before Linux 2.6, this
|
||||
// value was expressed in jiffies. Since Linux 2.6, the value is expressed in clock ticks
|
||||
// (divide by sysconf(_SC_CLK_TCK)).
|
||||
return parts[22-1], nil // starts at 1
|
||||
//
|
||||
// NOTE:
|
||||
// pos 2 could contain space and is inside `(` and `)`:
|
||||
// (2) comm %s
|
||||
// The filename of the executable, in parentheses.
|
||||
// This is visible whether or not the executable is
|
||||
// swapped out.
|
||||
//
|
||||
// the following is an example:
|
||||
// 89653 (gunicorn: maste) S 89630 89653 89653 0 -1 4194560 29689 28896 0 3 146 32 76 19 20 0 1 0 2971844 52965376 3920 18446744073709551615 1 1 0 0 0 0 0 16781312 137447943 0 0 0 17 1 0 0 0 0 0 0 0 0 0 0 0 0 0
|
||||
|
||||
// get parts after last `)`:
|
||||
s := strings.Split(stat, ")")
|
||||
parts := strings.Split(strings.TrimSpace(s[len(s)-1]), " ")
|
||||
return parts[22-3], nil // starts at 3 (after the filename pos `2`)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package system
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestParseStartTime(t *testing.T) {
|
||||
data := map[string]string{
|
||||
"4902 (gunicorn: maste) S 4885 4902 4902 0 -1 4194560 29683 29929 61 83 78 16 96 17 20 0 1 0 9126532 52965376 1903 18446744073709551615 4194304 7461796 140733928751520 140733928698072 139816984959091 0 0 16781312 137447943 1 0 0 17 3 0 0 9 0 0 9559488 10071156 33050624 140733928758775 140733928758945 140733928758945 140733928759264 0": "9126532",
|
||||
"9534 (cat) R 9323 9534 9323 34828 9534 4194304 95 0 0 0 0 0 0 0 20 0 1 0 9214966 7626752 168 18446744073709551615 4194304 4240332 140732237651568 140732237650920 140570710391216 0 0 0 0 0 0 0 17 1 0 0 0 0 0 6340112 6341364 21553152 140732237653865 140732237653885 140732237653885 140732237656047 0": "9214966",
|
||||
"24767 (irq/44-mei_me) S 2 0 0 0 -1 2129984 0 0 0 0 0 0 0 0 -51 0 1 0 8722075 0 0 18446744073709551615 0 0 0 0 0 0 0 2147483647 0 0 0 0 17 1 50 1 0 0 0 0 0 0 0 0 0 0 0": "8722075",
|
||||
}
|
||||
for line, startTime := range data {
|
||||
st, err := parseStartTime(line)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if startTime != st {
|
||||
t.Fatalf("expected start time %q but received %q", startTime, st)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue