in internal/ps/ps_linux.go [168:229]
func (p linuxClient) Memory(pid int) (int, error) {
baseProcDir := filepath.Join(p.procDir, strconv.Itoa(pid))
var stats []byte
var readErrors error
var readFile bool
var openFile string
// Read the smaps file. This is where the memory usage of the process is
// stored.
for _, fpath := range []string{"smaps", "smaps_rollup"} {
var err error
openFile = filepath.Join(baseProcDir, fpath)
stats, err = os.ReadFile(openFile) // NOLINT
if err != nil {
// If the error is not "not exist" means we failed to read it, in that
// case we don't fallback to other files.
if !os.IsNotExist(err) {
return 0, fmt.Errorf("error reading %s file: %w", fpath, err)
}
// If the error is "not exist", we fallback to other files and keep track
// of the errors.
if readErrors == nil {
readErrors = err
} else {
readErrors = fmt.Errorf("%w; %w", readErrors, err)
}
}
readFile = true
if err == nil {
break
}
}
if !readFile && readErrors != nil {
return 0, fmt.Errorf("error reading smaps/smaps_rollup file: %w", readErrors)
}
statsLines := strings.Split(string(stats), "\n")
foundRss := false
var memUsage int
// Now find the memory line. This line is the RSS line.
for _, line := range statsLines {
if strings.HasPrefix(line, "Rss") {
foundRss = true
partial, err := strconv.Atoi(strings.Fields(line)[1])
if err != nil {
return 0, fmt.Errorf("error parsing RSS line: %w", err)
}
memUsage += partial
}
}
if !foundRss {
return 0, fmt.Errorf("no RSS line found in %s file", openFile)
}
return memUsage, nil
}