allow to pass context values to override environment variables

pull/1439/head
Antoine Toulme 2 years ago
parent 32e8a92ad6
commit 38b94668ea

@ -96,7 +96,7 @@ func Times(percpu bool) ([]TimesStat, error) {
} }
func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
filename := common.HostProc("stat") filename := common.HostProcWithContext(ctx, "stat")
lines := []string{} lines := []string{}
if percpu { if percpu {
statlines, err := common.ReadLines(filename) statlines, err := common.ReadLines(filename)
@ -126,17 +126,17 @@ func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) {
return ret, nil return ret, nil
} }
func sysCPUPath(cpu int32, relPath string) string { func sysCPUPath(ctx context.Context, cpu int32, relPath string) string {
return common.HostSys(fmt.Sprintf("devices/system/cpu/cpu%d", cpu), relPath) return common.HostSysWithContext(ctx, fmt.Sprintf("devices/system/cpu/cpu%d", cpu), relPath)
} }
func finishCPUInfo(c *InfoStat) { func finishCPUInfo(ctx context.Context, c *InfoStat) {
var lines []string var lines []string
var err error var err error
var value float64 var value float64
if len(c.CoreID) == 0 { if len(c.CoreID) == 0 {
lines, err = common.ReadLines(sysCPUPath(c.CPU, "topology/core_id")) lines, err = common.ReadLines(sysCPUPath(ctx, c.CPU, "topology/core_id"))
if err == nil { if err == nil {
c.CoreID = lines[0] c.CoreID = lines[0]
} }
@ -145,7 +145,7 @@ func finishCPUInfo(c *InfoStat) {
// override the value of c.Mhz with cpufreq/cpuinfo_max_freq regardless // override the value of c.Mhz with cpufreq/cpuinfo_max_freq regardless
// of the value from /proc/cpuinfo because we want to report the maximum // of the value from /proc/cpuinfo because we want to report the maximum
// clock-speed of the CPU for c.Mhz, matching the behaviour of Windows // clock-speed of the CPU for c.Mhz, matching the behaviour of Windows
lines, err = common.ReadLines(sysCPUPath(c.CPU, "cpufreq/cpuinfo_max_freq")) lines, err = common.ReadLines(sysCPUPath(ctx, c.CPU, "cpufreq/cpuinfo_max_freq"))
// if we encounter errors below such as there are no cpuinfo_max_freq file, // if we encounter errors below such as there are no cpuinfo_max_freq file,
// we just ignore. so let Mhz is 0. // we just ignore. so let Mhz is 0.
if err != nil || len(lines) == 0 { if err != nil || len(lines) == 0 {
@ -173,7 +173,7 @@ func Info() ([]InfoStat, error) {
} }
func InfoWithContext(ctx context.Context) ([]InfoStat, error) { func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
filename := common.HostProc("cpuinfo") filename := common.HostProcWithContext(ctx, "cpuinfo")
lines, _ := common.ReadLines(filename) lines, _ := common.ReadLines(filename)
var ret []InfoStat var ret []InfoStat
@ -193,7 +193,7 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
processorName = value processorName = value
case "processor", "cpu number": case "processor", "cpu number":
if c.CPU >= 0 { if c.CPU >= 0 {
finishCPUInfo(&c) finishCPUInfo(ctx, &c)
ret = append(ret, c) ret = append(ret, c)
} }
c = InfoStat{Cores: 1, ModelName: processorName} c = InfoStat{Cores: 1, ModelName: processorName}
@ -301,7 +301,7 @@ func InfoWithContext(ctx context.Context) ([]InfoStat, error) {
} }
} }
if c.CPU >= 0 { if c.CPU >= 0 {
finishCPUInfo(&c) finishCPUInfo(ctx, &c)
ret = append(ret, c) ret = append(ret, c)
} }
return ret, nil return ret, nil
@ -390,7 +390,7 @@ func CountsWithContext(ctx context.Context, logical bool) (int, error) {
if logical { if logical {
ret := 0 ret := 0
// https://github.com/giampaolo/psutil/blob/d01a9eaa35a8aadf6c519839e987a49d8be2d891/psutil/_pslinux.py#L599 // https://github.com/giampaolo/psutil/blob/d01a9eaa35a8aadf6c519839e987a49d8be2d891/psutil/_pslinux.py#L599
procCpuinfo := common.HostProc("cpuinfo") procCpuinfo := common.HostProcWithContext(ctx, "cpuinfo")
lines, err := common.ReadLines(procCpuinfo) lines, err := common.ReadLines(procCpuinfo)
if err == nil { if err == nil {
for _, line := range lines { for _, line := range lines {
@ -404,7 +404,7 @@ func CountsWithContext(ctx context.Context, logical bool) (int, error) {
} }
} }
if ret == 0 { if ret == 0 {
procStat := common.HostProc("stat") procStat := common.HostProcWithContext(ctx, "stat")
lines, err = common.ReadLines(procStat) lines, err = common.ReadLines(procStat)
if err != nil { if err != nil {
return 0, err return 0, err
@ -425,7 +425,7 @@ func CountsWithContext(ctx context.Context, logical bool) (int, error) {
// https://github.com/giampaolo/psutil/pull/1727#issuecomment-707624964 // https://github.com/giampaolo/psutil/pull/1727#issuecomment-707624964
// https://lkml.org/lkml/2019/2/26/41 // https://lkml.org/lkml/2019/2/26/41
for _, glob := range []string{"devices/system/cpu/cpu[0-9]*/topology/core_cpus_list", "devices/system/cpu/cpu[0-9]*/topology/thread_siblings_list"} { for _, glob := range []string{"devices/system/cpu/cpu[0-9]*/topology/core_cpus_list", "devices/system/cpu/cpu[0-9]*/topology/thread_siblings_list"} {
if files, err := filepath.Glob(common.HostSys(glob)); err == nil { if files, err := filepath.Glob(common.HostSysWithContext(ctx, glob)); err == nil {
for _, file := range files { for _, file := range files {
lines, err := common.ReadLines(file) lines, err := common.ReadLines(file)
if err != nil || len(lines) != 1 { if err != nil || len(lines) != 1 {
@ -440,7 +440,7 @@ func CountsWithContext(ctx context.Context, logical bool) (int, error) {
} }
} }
// https://github.com/giampaolo/psutil/blob/122174a10b75c9beebe15f6c07dcf3afbe3b120d/psutil/_pslinux.py#L631-L652 // https://github.com/giampaolo/psutil/blob/122174a10b75c9beebe15f6c07dcf3afbe3b120d/psutil/_pslinux.py#L631-L652
filename := common.HostProc("cpuinfo") filename := common.HostProcWithContext(ctx, "cpuinfo")
lines, err := common.ReadLines(filename) lines, err := common.ReadLines(filename)
if err != nil { if err != nil {
return 0, err return 0, err

@ -260,10 +260,10 @@ func readMountFile(root string) (lines []string, useMounts bool, filename string
func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) { func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) {
// by default, try "/proc/1/..." first // by default, try "/proc/1/..." first
root := common.HostProc(path.Join("1")) root := common.HostProcWithContext(ctx, path.Join("1"))
// force preference for dirname of HOST_PROC_MOUNTINFO, if set #1271 // force preference for dirname of HOST_PROC_MOUNTINFO, if set #1271
hpmPath := os.Getenv("HOST_PROC_MOUNTINFO") hpmPath := common.HostProcMountInfoWithContext(ctx)
if hpmPath != "" { if hpmPath != "" {
root = filepath.Dir(hpmPath) root = filepath.Dir(hpmPath)
} }
@ -274,13 +274,13 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
return nil, err return nil, err
} }
// fallback to "/proc/self/..." #1159 // fallback to "/proc/self/..." #1159
lines, useMounts, filename, err = readMountFile(common.HostProc(path.Join("self"))) lines, useMounts, filename, err = readMountFile(common.HostProcWithContext(ctx, path.Join("self")))
if err != nil { if err != nil {
return nil, err return nil, err
} }
} }
fs, err := getFileSystems() fs, err := getFileSystems(ctx)
if err != nil && !all { if err != nil && !all {
return nil, err return nil, err
} }
@ -342,7 +342,7 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
} }
if strings.HasPrefix(d.Device, "/dev/mapper/") { if strings.HasPrefix(d.Device, "/dev/mapper/") {
devpath, err := filepath.EvalSymlinks(common.HostDev(strings.Replace(d.Device, "/dev", "", 1))) devpath, err := filepath.EvalSymlinks(common.HostDevWithContext(ctx, strings.Replace(d.Device, "/dev", "", 1)))
if err == nil { if err == nil {
d.Device = devpath d.Device = devpath
} }
@ -351,7 +351,7 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
// /dev/root is not the real device name // /dev/root is not the real device name
// so we get the real device name from its major/minor number // so we get the real device name from its major/minor number
if d.Device == "/dev/root" { if d.Device == "/dev/root" {
devpath, err := os.Readlink(common.HostSys("/dev/block/" + blockDeviceID)) devpath, err := os.Readlink(common.HostSysWithContext(ctx, "/dev/block/"+blockDeviceID))
if err == nil { if err == nil {
d.Device = strings.Replace(d.Device, "root", filepath.Base(devpath), 1) d.Device = strings.Replace(d.Device, "root", filepath.Base(devpath), 1)
} }
@ -364,8 +364,8 @@ func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, erro
} }
// getFileSystems returns supported filesystems from /proc/filesystems // getFileSystems returns supported filesystems from /proc/filesystems
func getFileSystems() ([]string, error) { func getFileSystems(ctx context.Context) ([]string, error) {
filename := common.HostProc("filesystems") filename := common.HostProcWithContext(ctx, "filesystems")
lines, err := common.ReadLines(filename) lines, err := common.ReadLines(filename)
if err != nil { if err != nil {
return nil, err return nil, err
@ -387,7 +387,7 @@ func getFileSystems() ([]string, error) {
} }
func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) { func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) {
filename := common.HostProc("diskstats") filename := common.HostProcWithContext(ctx, "diskstats")
lines, err := common.ReadLines(filename) lines, err := common.ReadLines(filename)
if err != nil { if err != nil {
return nil, err return nil, err
@ -492,7 +492,7 @@ func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
minor := unix.Minor(uint64(stat.Rdev)) minor := unix.Minor(uint64(stat.Rdev))
// Try to get the serial from udev data // Try to get the serial from udev data
udevDataPath := common.HostRun(fmt.Sprintf("udev/data/b%d:%d", major, minor)) udevDataPath := common.HostRunWithContext(ctx, fmt.Sprintf("udev/data/b%d:%d", major, minor))
if udevdata, err := ioutil.ReadFile(udevDataPath); err == nil { if udevdata, err := ioutil.ReadFile(udevDataPath); err == nil {
scanner := bufio.NewScanner(bytes.NewReader(udevdata)) scanner := bufio.NewScanner(bytes.NewReader(udevdata))
for scanner.Scan() { for scanner.Scan() {
@ -505,7 +505,7 @@ func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
// Try to get the serial from sysfs, look at the disk device (minor 0) directly // Try to get the serial from sysfs, look at the disk device (minor 0) directly
// because if it is a partition it is not going to contain any device information // because if it is a partition it is not going to contain any device information
devicePath := common.HostSys(fmt.Sprintf("dev/block/%d:0/device", major)) devicePath := common.HostSysWithContext(ctx, fmt.Sprintf("dev/block/%d:0/device", major))
model, _ := ioutil.ReadFile(filepath.Join(devicePath, "model")) model, _ := ioutil.ReadFile(filepath.Join(devicePath, "model"))
serial, _ := ioutil.ReadFile(filepath.Join(devicePath, "serial")) serial, _ := ioutil.ReadFile(filepath.Join(devicePath, "serial"))
if len(model) > 0 && len(serial) > 0 { if len(model) > 0 && len(serial) > 0 {
@ -516,7 +516,7 @@ func SerialNumberWithContext(ctx context.Context, name string) (string, error) {
func LabelWithContext(ctx context.Context, name string) (string, error) { func LabelWithContext(ctx context.Context, name string) (string, error) {
// Try label based on devicemapper name // Try label based on devicemapper name
dmname_filename := common.HostSys(fmt.Sprintf("block/%s/dm/name", name)) dmname_filename := common.HostSysWithContext(ctx, fmt.Sprintf("block/%s/dm/name", name))
if !common.PathExists(dmname_filename) { if !common.PathExists(dmname_filename) {
return "", nil return "", nil

@ -100,7 +100,7 @@ func CgroupCPUUsage(containerID string, base string) (float64, error) {
} }
func CgroupCPUWithContext(ctx context.Context, containerID string, base string) (*CgroupCPUStat, error) { func CgroupCPUWithContext(ctx context.Context, containerID string, base string) (*CgroupCPUStat, error) {
statfile := getCgroupFilePath(containerID, base, "cpuacct", "cpuacct.stat") statfile := getCgroupFilePath(ctx, containerID, base, "cpuacct", "cpuacct.stat")
lines, err := common.ReadLines(statfile) lines, err := common.ReadLines(statfile)
if err != nil { if err != nil {
return nil, err return nil, err
@ -136,7 +136,7 @@ func CgroupCPUWithContext(ctx context.Context, containerID string, base string)
} }
func CgroupCPUUsageWithContext(ctx context.Context, containerID, base string) (float64, error) { func CgroupCPUUsageWithContext(ctx context.Context, containerID, base string) (float64, error) {
usagefile := getCgroupFilePath(containerID, base, "cpuacct", "cpuacct.usage") usagefile := getCgroupFilePath(ctx, containerID, base, "cpuacct", "cpuacct.usage")
lines, err := common.ReadLinesOffsetN(usagefile, 0, 1) lines, err := common.ReadLinesOffsetN(usagefile, 0, 1)
if err != nil { if err != nil {
return 0.0, err return 0.0, err
@ -159,11 +159,11 @@ func CgroupCPUUsageDocker(containerid string) (float64, error) {
} }
func CgroupCPUDockerWithContext(ctx context.Context, containerid string) (*CgroupCPUStat, error) { func CgroupCPUDockerWithContext(ctx context.Context, containerid string) (*CgroupCPUStat, error) {
return CgroupCPUWithContext(ctx, containerid, common.HostSys("fs/cgroup/cpuacct/docker")) return CgroupCPUWithContext(ctx, containerid, common.HostSysWithContext(ctx, "fs/cgroup/cpuacct/docker"))
} }
func CgroupCPUDockerUsageWithContext(ctx context.Context, containerid string) (float64, error) { func CgroupCPUDockerUsageWithContext(ctx context.Context, containerid string) (float64, error) {
return CgroupCPUUsageWithContext(ctx, containerid, common.HostSys("fs/cgroup/cpuacct/docker")) return CgroupCPUUsageWithContext(ctx, containerid, common.HostSysWithContext(ctx, "fs/cgroup/cpuacct/docker"))
} }
func CgroupMem(containerID string, base string) (*CgroupMemStat, error) { func CgroupMem(containerID string, base string) (*CgroupMemStat, error) {
@ -171,7 +171,7 @@ func CgroupMem(containerID string, base string) (*CgroupMemStat, error) {
} }
func CgroupMemWithContext(ctx context.Context, containerID string, base string) (*CgroupMemStat, error) { func CgroupMemWithContext(ctx context.Context, containerID string, base string) (*CgroupMemStat, error) {
statfile := getCgroupFilePath(containerID, base, "memory", "memory.stat") statfile := getCgroupFilePath(ctx, containerID, base, "memory", "memory.stat")
// empty containerID means all cgroup // empty containerID means all cgroup
if len(containerID) == 0 { if len(containerID) == 0 {
@ -246,19 +246,19 @@ func CgroupMemWithContext(ctx context.Context, containerID string, base string)
} }
} }
r, err := getCgroupMemFile(containerID, base, "memory.usage_in_bytes") r, err := getCgroupMemFile(ctx, containerID, base, "memory.usage_in_bytes")
if err == nil { if err == nil {
ret.MemUsageInBytes = r ret.MemUsageInBytes = r
} }
r, err = getCgroupMemFile(containerID, base, "memory.max_usage_in_bytes") r, err = getCgroupMemFile(ctx, containerID, base, "memory.max_usage_in_bytes")
if err == nil { if err == nil {
ret.MemMaxUsageInBytes = r ret.MemMaxUsageInBytes = r
} }
r, err = getCgroupMemFile(containerID, base, "memory.limit_in_bytes") r, err = getCgroupMemFile(ctx, containerID, base, "memory.limit_in_bytes")
if err == nil { if err == nil {
ret.MemLimitInBytes = r ret.MemLimitInBytes = r
} }
r, err = getCgroupMemFile(containerID, base, "memory.failcnt") r, err = getCgroupMemFile(ctx, containerID, base, "memory.failcnt")
if err == nil { if err == nil {
ret.MemFailCnt = r ret.MemFailCnt = r
} }
@ -271,27 +271,27 @@ func CgroupMemDocker(containerID string) (*CgroupMemStat, error) {
} }
func CgroupMemDockerWithContext(ctx context.Context, containerID string) (*CgroupMemStat, error) { func CgroupMemDockerWithContext(ctx context.Context, containerID string) (*CgroupMemStat, error) {
return CgroupMemWithContext(ctx, containerID, common.HostSys("fs/cgroup/memory/docker")) return CgroupMemWithContext(ctx, containerID, common.HostSysWithContext(ctx, "fs/cgroup/memory/docker"))
} }
// getCgroupFilePath constructs file path to get targeted stats file. // getCgroupFilePath constructs file path to get targeted stats file.
func getCgroupFilePath(containerID, base, target, file string) string { func getCgroupFilePath(ctx context.Context, containerID, base, target, file string) string {
if len(base) == 0 { if len(base) == 0 {
base = common.HostSys(fmt.Sprintf("fs/cgroup/%s/docker", target)) base = common.HostSysWithContext(ctx, fmt.Sprintf("fs/cgroup/%s/docker", target))
} }
statfile := path.Join(base, containerID, file) statfile := path.Join(base, containerID, file)
if _, err := os.Stat(statfile); os.IsNotExist(err) { if _, err := os.Stat(statfile); os.IsNotExist(err) {
statfile = path.Join( statfile = path.Join(
common.HostSys(fmt.Sprintf("fs/cgroup/%s/system.slice", target)), "docker-"+containerID+".scope", file) common.HostSysWithContext(ctx, fmt.Sprintf("fs/cgroup/%s/system.slice", target)), "docker-"+containerID+".scope", file)
} }
return statfile return statfile
} }
// getCgroupMemFile reads a cgroup file and return the contents as uint64. // getCgroupMemFile reads a cgroup file and return the contents as uint64.
func getCgroupMemFile(containerID, base, file string) (uint64, error) { func getCgroupMemFile(ctx context.Context, containerID, base, file string) (uint64, error) {
statfile := getCgroupFilePath(containerID, base, "memory", file) statfile := getCgroupFilePath(ctx, containerID, base, "memory", file)
lines, err := common.ReadLines(statfile) lines, err := common.ReadLines(statfile)
if err != nil { if err != nil {
return 0, err return 0, err

@ -46,7 +46,7 @@ func CgroupCPUDocker(containerid string) (*CgroupCPUStat, error) {
} }
func CgroupCPUDockerWithContext(ctx context.Context, containerid string) (*CgroupCPUStat, error) { func CgroupCPUDockerWithContext(ctx context.Context, containerid string) (*CgroupCPUStat, error) {
return CgroupCPU(containerid, common.HostSys("fs/cgroup/cpuacct/docker")) return CgroupCPU(containerid, common.HostSysWithContext(ctx, "fs/cgroup/cpuacct/docker"))
} }
func CgroupMem(containerid string, base string) (*CgroupMemStat, error) { func CgroupMem(containerid string, base string) (*CgroupMemStat, error) {
@ -62,5 +62,5 @@ func CgroupMemDocker(containerid string) (*CgroupMemStat, error) {
} }
func CgroupMemDockerWithContext(ctx context.Context, containerid string) (*CgroupMemStat, error) { func CgroupMemDockerWithContext(ctx context.Context, containerid string) (*CgroupMemStat, error) {
return CgroupMem(containerid, common.HostSys("fs/cgroup/memory/docker")) return CgroupMem(containerid, common.HostSysWithContext(ctx, "fs/cgroup/memory/docker"))
} }

@ -35,9 +35,9 @@ const (
) )
func HostIDWithContext(ctx context.Context) (string, error) { func HostIDWithContext(ctx context.Context) (string, error) {
sysProductUUID := common.HostSys("class/dmi/id/product_uuid") sysProductUUID := common.HostSysWithContext(ctx, "class/dmi/id/product_uuid")
machineID := common.HostEtc("machine-id") machineID := common.HostEtcWithContext(ctx, "machine-id")
procSysKernelRandomBootID := common.HostProc("sys/kernel/random/boot_id") procSysKernelRandomBootID := common.HostProcWithContext(ctx, "sys/kernel/random/boot_id")
switch { switch {
// In order to read this file, needs to be supported by kernel/arch and run as root // In order to read this file, needs to be supported by kernel/arch and run as root
// so having fallback is important // so having fallback is important
@ -67,7 +67,7 @@ func HostIDWithContext(ctx context.Context) (string, error) {
} }
func numProcs(ctx context.Context) (uint64, error) { func numProcs(ctx context.Context) (uint64, error) {
return common.NumProcs() return common.NumProcsWithContext(ctx)
} }
func BootTimeWithContext(ctx context.Context) (uint64, error) { func BootTimeWithContext(ctx context.Context) (uint64, error) {
@ -83,7 +83,7 @@ func UptimeWithContext(ctx context.Context) (uint64, error) {
} }
func UsersWithContext(ctx context.Context) ([]UserStat, error) { func UsersWithContext(ctx context.Context) ([]UserStat, error) {
utmpfile := common.HostVar("run/utmp") utmpfile := common.HostVarWithContext(ctx, "run/utmp")
file, err := os.Open(utmpfile) file, err := os.Open(utmpfile)
if err != nil { if err != nil {
@ -124,10 +124,10 @@ func UsersWithContext(ctx context.Context) ([]UserStat, error) {
return ret, nil return ret, nil
} }
func getlsbStruct() (*lsbStruct, error) { func getlsbStruct(ctx context.Context) (*lsbStruct, error) {
ret := &lsbStruct{} ret := &lsbStruct{}
if common.PathExists(common.HostEtc("lsb-release")) { if common.PathExists(common.HostEtcWithContext(ctx, "lsb-release")) {
contents, err := common.ReadLines(common.HostEtc("lsb-release")) contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "lsb-release"))
if err != nil { if err != nil {
return ret, err // return empty return ret, err // return empty
} }
@ -175,31 +175,31 @@ func getlsbStruct() (*lsbStruct, error) {
} }
func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) { func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) {
lsb, err := getlsbStruct() lsb, err := getlsbStruct(ctx)
if err != nil { if err != nil {
lsb = &lsbStruct{} lsb = &lsbStruct{}
} }
if common.PathExistsWithContents(common.HostEtc("oracle-release")) { if common.PathExistsWithContents(common.HostEtcWithContext(ctx, "oracle-release")) {
platform = "oracle" platform = "oracle"
contents, err := common.ReadLines(common.HostEtc("oracle-release")) contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "oracle-release"))
if err == nil { if err == nil {
version = getRedhatishVersion(contents) version = getRedhatishVersion(contents)
} }
} else if common.PathExistsWithContents(common.HostEtc("enterprise-release")) { } else if common.PathExistsWithContents(common.HostEtcWithContext(ctx, "enterprise-release")) {
platform = "oracle" platform = "oracle"
contents, err := common.ReadLines(common.HostEtc("enterprise-release")) contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "enterprise-release"))
if err == nil { if err == nil {
version = getRedhatishVersion(contents) version = getRedhatishVersion(contents)
} }
} else if common.PathExistsWithContents(common.HostEtc("slackware-version")) { } else if common.PathExistsWithContents(common.HostEtcWithContext(ctx, "slackware-version")) {
platform = "slackware" platform = "slackware"
contents, err := common.ReadLines(common.HostEtc("slackware-version")) contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "slackware-version"))
if err == nil { if err == nil {
version = getSlackwareVersion(contents) version = getSlackwareVersion(contents)
} }
} else if common.PathExistsWithContents(common.HostEtc("debian_version")) { } else if common.PathExistsWithContents(common.HostEtcWithContext(ctx, "debian_version")) {
if lsb.ID == "Ubuntu" { if lsb.ID == "Ubuntu" {
platform = "ubuntu" platform = "ubuntu"
version = lsb.Release version = lsb.Release
@ -218,53 +218,53 @@ func PlatformInformationWithContext(ctx context.Context) (platform string, famil
} else { } else {
platform = "debian" platform = "debian"
} }
contents, err := common.ReadLines(common.HostEtc("debian_version")) contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "debian_version"))
if err == nil && len(contents) > 0 && contents[0] != "" { if err == nil && len(contents) > 0 && contents[0] != "" {
version = contents[0] version = contents[0]
} }
} }
} else if common.PathExists(common.HostEtc("neokylin-release")) { } else if common.PathExists(common.HostEtcWithContext(ctx, "neokylin-release")) {
contents, err := common.ReadLines(common.HostEtc("neokylin-release")) contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "neokylin-release"))
if err == nil { if err == nil {
version = getRedhatishVersion(contents) version = getRedhatishVersion(contents)
platform = getRedhatishPlatform(contents) platform = getRedhatishPlatform(contents)
} }
} else if common.PathExists(common.HostEtc("redhat-release")) { } else if common.PathExists(common.HostEtcWithContext(ctx, "redhat-release")) {
contents, err := common.ReadLines(common.HostEtc("redhat-release")) contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "redhat-release"))
if err == nil { if err == nil {
version = getRedhatishVersion(contents) version = getRedhatishVersion(contents)
platform = getRedhatishPlatform(contents) platform = getRedhatishPlatform(contents)
} }
} else if common.PathExists(common.HostEtc("system-release")) { } else if common.PathExists(common.HostEtcWithContext(ctx, "system-release")) {
contents, err := common.ReadLines(common.HostEtc("system-release")) contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "system-release"))
if err == nil { if err == nil {
version = getRedhatishVersion(contents) version = getRedhatishVersion(contents)
platform = getRedhatishPlatform(contents) platform = getRedhatishPlatform(contents)
} }
} else if common.PathExists(common.HostEtc("gentoo-release")) { } else if common.PathExists(common.HostEtcWithContext(ctx, "gentoo-release")) {
platform = "gentoo" platform = "gentoo"
contents, err := common.ReadLines(common.HostEtc("gentoo-release")) contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "gentoo-release"))
if err == nil { if err == nil {
version = getRedhatishVersion(contents) version = getRedhatishVersion(contents)
} }
} else if common.PathExists(common.HostEtc("SuSE-release")) { } else if common.PathExists(common.HostEtcWithContext(ctx, "SuSE-release")) {
contents, err := common.ReadLines(common.HostEtc("SuSE-release")) contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "SuSE-release"))
if err == nil { if err == nil {
version = getSuseVersion(contents) version = getSuseVersion(contents)
platform = getSusePlatform(contents) platform = getSusePlatform(contents)
} }
// TODO: slackware detecion // TODO: slackware detecion
} else if common.PathExists(common.HostEtc("arch-release")) { } else if common.PathExists(common.HostEtcWithContext(ctx, "arch-release")) {
platform = "arch" platform = "arch"
version = lsb.Release version = lsb.Release
} else if common.PathExists(common.HostEtc("alpine-release")) { } else if common.PathExists(common.HostEtcWithContext(ctx, "alpine-release")) {
platform = "alpine" platform = "alpine"
contents, err := common.ReadLines(common.HostEtc("alpine-release")) contents, err := common.ReadLines(common.HostEtcWithContext(ctx, "alpine-release"))
if err == nil && len(contents) > 0 && contents[0] != "" { if err == nil && len(contents) > 0 && contents[0] != "" {
version = contents[0] version = contents[0]
} }
} else if common.PathExists(common.HostEtc("os-release")) { } else if common.PathExists(common.HostEtcWithContext(ctx, "os-release")) {
p, v, err := common.GetOSRelease() p, v, err := common.GetOSReleaseWithContext(ctx)
if err == nil { if err == nil {
platform = p platform = p
version = v version = v
@ -390,14 +390,14 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err
// Only the temp*_input file provides current temperature // Only the temp*_input file provides current temperature
// value in millidegree Celsius as reported by the temperature to the device: // value in millidegree Celsius as reported by the temperature to the device:
// https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface // https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
if files, err = filepath.Glob(common.HostSys("/class/hwmon/hwmon*/temp*_input")); err != nil { if files, err = filepath.Glob(common.HostSysWithContext(ctx, "/class/hwmon/hwmon*/temp*_input")); err != nil {
return temperatures, err return temperatures, err
} }
if len(files) == 0 { if len(files) == 0 {
// CentOS has an intermediate /device directory: // CentOS has an intermediate /device directory:
// https://github.com/giampaolo/psutil/issues/971 // https://github.com/giampaolo/psutil/issues/971
if files, err = filepath.Glob(common.HostSys("/class/hwmon/hwmon*/device/temp*_input")); err != nil { if files, err = filepath.Glob(common.HostSysWithContext(ctx, "/class/hwmon/hwmon*/device/temp*_input")); err != nil {
return temperatures, err return temperatures, err
} }
} }
@ -405,7 +405,7 @@ func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, err
var warns Warnings var warns Warnings
if len(files) == 0 { // handle distributions without hwmon, like raspbian #391, parse legacy thermal_zone files if len(files) == 0 { // handle distributions without hwmon, like raspbian #391, parse legacy thermal_zone files
files, err = filepath.Glob(common.HostSys("/class/thermal/thermal_zone*/")) files, err = filepath.Glob(common.HostSysWithContext(ctx, "/class/thermal/thermal_zone*/"))
if err != nil { if err != nil {
return temperatures, err return temperatures, err
} }

@ -32,6 +32,10 @@ var (
ErrTimeout = errors.New("command timed out") ErrTimeout = errors.New("command timed out")
) )
type envKey string
var Env = envKey("string")
type Invoker interface { type Invoker interface {
Command(string, ...string) ([]byte, error) Command(string, ...string) ([]byte, error)
CommandWithContext(context.Context, string, ...string) ([]byte, error) CommandWithContext(context.Context, string, ...string) ([]byte, error)
@ -321,6 +325,23 @@ func PathExistsWithContents(filename string) bool {
return info.Size() > 4 // at least 4 bytes return info.Size() > 4 // at least 4 bytes
} }
// GetEnvWithContext retrieves the environment variable key. If it does not exist it returns the default.
// The context may optionally contain a map superseding os.Env.
func GetEnvWithContext(ctx context.Context, key string, dfault string, combineWith ...string) string {
var value string
if env, ok := ctx.Value(Env).(map[string]string); ok {
value = env[key]
}
if value == "" {
value = os.Getenv(key)
}
if value == "" {
value = dfault
}
return combine(value, combineWith)
}
// GetEnv retrieves the environment variable key. If it does not exist it returns the default. // GetEnv retrieves the environment variable key. If it does not exist it returns the default.
func GetEnv(key string, dfault string, combineWith ...string) string { func GetEnv(key string, dfault string, combineWith ...string) string {
value := os.Getenv(key) value := os.Getenv(key)
@ -328,6 +349,10 @@ func GetEnv(key string, dfault string, combineWith ...string) string {
value = dfault value = dfault
} }
return combine(value, combineWith)
}
func combine(value string, combineWith []string) string {
switch len(combineWith) { switch len(combineWith) {
case 0: case 0:
return value return value
@ -341,34 +366,73 @@ func GetEnv(key string, dfault string, combineWith ...string) string {
} }
} }
// Deprecated: use HostProcWithContext instead
func HostProc(combineWith ...string) string { func HostProc(combineWith ...string) string {
return GetEnv("HOST_PROC", "/proc", combineWith...) return GetEnv("HOST_PROC", "/proc", combineWith...)
} }
// Deprecated: use HostSysWithContext instead
func HostSys(combineWith ...string) string { func HostSys(combineWith ...string) string {
return GetEnv("HOST_SYS", "/sys", combineWith...) return GetEnv("HOST_SYS", "/sys", combineWith...)
} }
// Deprecated: use HostEtcWithContext instead
func HostEtc(combineWith ...string) string { func HostEtc(combineWith ...string) string {
return GetEnv("HOST_ETC", "/etc", combineWith...) return GetEnv("HOST_ETC", "/etc", combineWith...)
} }
// Deprecated: use HostVarWithContext instead
func HostVar(combineWith ...string) string { func HostVar(combineWith ...string) string {
return GetEnv("HOST_VAR", "/var", combineWith...) return GetEnv("HOST_VAR", "/var", combineWith...)
} }
// Deprecated: use HostRunWithContext instead
func HostRun(combineWith ...string) string { func HostRun(combineWith ...string) string {
return GetEnv("HOST_RUN", "/run", combineWith...) return GetEnv("HOST_RUN", "/run", combineWith...)
} }
// Deprecated: use HostDevWithContext instead
func HostDev(combineWith ...string) string { func HostDev(combineWith ...string) string {
return GetEnv("HOST_DEV", "/dev", combineWith...) return GetEnv("HOST_DEV", "/dev", combineWith...)
} }
// Deprecated: use HostRootWithContext instead
func HostRoot(combineWith ...string) string { func HostRoot(combineWith ...string) string {
return GetEnv("HOST_ROOT", "/", combineWith...) return GetEnv("HOST_ROOT", "/", combineWith...)
} }
func HostProcWithContext(ctx context.Context, combineWith ...string) string {
return GetEnvWithContext(ctx, "HOST_PROC", "/proc", combineWith...)
}
func HostProcMountInfoWithContext(ctx context.Context, combineWith ...string) string {
return GetEnvWithContext(ctx, "HOST_PROC_MOUNTINFO", "", combineWith...)
}
func HostSysWithContext(ctx context.Context, combineWith ...string) string {
return GetEnvWithContext(ctx, "HOST_SYS", "/sys", combineWith...)
}
func HostEtcWithContext(ctx context.Context, combineWith ...string) string {
return GetEnvWithContext(ctx, "HOST_ETC", "/etc", combineWith...)
}
func HostVarWithContext(ctx context.Context, combineWith ...string) string {
return GetEnvWithContext(ctx, "HOST_VAR", "/var", combineWith...)
}
func HostRunWithContext(ctx context.Context, combineWith ...string) string {
return GetEnvWithContext(ctx, "HOST_RUN", "/run", combineWith...)
}
func HostDevWithContext(ctx context.Context, combineWith ...string) string {
return GetEnvWithContext(ctx, "HOST_DEV", "/dev", combineWith...)
}
func HostRootWithContext(ctx context.Context, combineWith ...string) string {
return GetEnvWithContext(ctx, "HOST_ROOT", "/", combineWith...)
}
// getSysctrlEnv sets LC_ALL=C in a list of env vars for use when running // getSysctrlEnv sets LC_ALL=C in a list of env vars for use when running
// sysctl commands (see DoSysctrl). // sysctl commands (see DoSysctrl).
func getSysctrlEnv(env []string) []string { func getSysctrlEnv(env []string) []string {

@ -30,8 +30,13 @@ func DoSysctrl(mib string) ([]string, error) {
return values, nil return values, nil
} }
// Deprecated: use NumProcsWithContext instead
func NumProcs() (uint64, error) { func NumProcs() (uint64, error) {
f, err := os.Open(HostProc()) return NumProcsWithContext(context.Background())
}
func NumProcsWithContext(ctx context.Context) (uint64, error) {
f, err := os.Open(HostProcWithContext(ctx))
if err != nil { if err != nil {
return 0, err return 0, err
} }
@ -67,7 +72,7 @@ func BootTimeWithContext(ctx context.Context) (uint64, error) {
statFile = "uptime" statFile = "uptime"
} }
filename := HostProc(statFile) filename := HostProcWithContext(ctx, statFile)
lines, err := ReadLines(filename) lines, err := ReadLines(filename)
if os.IsPermission(err) { if os.IsPermission(err) {
var info syscall.Sysinfo_t var info syscall.Sysinfo_t
@ -139,7 +144,7 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
} }
cachedVirtMutex.RUnlock() cachedVirtMutex.RUnlock()
filename := HostProc("xen") filename := HostProcWithContext(ctx, "xen")
if PathExists(filename) { if PathExists(filename) {
system = "xen" system = "xen"
role = "guest" // assume guest role = "guest" // assume guest
@ -154,7 +159,7 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
} }
} }
filename = HostProc("modules") filename = HostProcWithContext(ctx, "modules")
if PathExists(filename) { if PathExists(filename) {
contents, err := ReadLines(filename) contents, err := ReadLines(filename)
if err == nil { if err == nil {
@ -177,7 +182,7 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
} }
} }
filename = HostProc("cpuinfo") filename = HostProcWithContext(ctx, "cpuinfo")
if PathExists(filename) { if PathExists(filename) {
contents, err := ReadLines(filename) contents, err := ReadLines(filename)
if err == nil { if err == nil {
@ -190,7 +195,7 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
} }
} }
filename = HostProc("bus/pci/devices") filename = HostProcWithContext(ctx, "bus/pci/devices")
if PathExists(filename) { if PathExists(filename) {
contents, err := ReadLines(filename) contents, err := ReadLines(filename)
if err == nil { if err == nil {
@ -200,7 +205,7 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
} }
} }
filename = HostProc() filename = HostProcWithContext(ctx)
if PathExists(filepath.Join(filename, "bc", "0")) { if PathExists(filepath.Join(filename, "bc", "0")) {
system = "openvz" system = "openvz"
role = "host" role = "host"
@ -251,15 +256,15 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
} }
} }
if PathExists(HostEtc("os-release")) { if PathExists(HostEtcWithContext(ctx, "os-release")) {
p, _, err := GetOSRelease() p, _, err := GetOSReleaseWithContext(ctx)
if err == nil && p == "coreos" { if err == nil && p == "coreos" {
system = "rkt" // Is it true? system = "rkt" // Is it true?
role = "host" role = "host"
} }
} }
if PathExists(HostRoot(".dockerenv")) { if PathExists(HostRootWithContext(ctx, ".dockerenv")) {
system = "docker" system = "docker"
role = "guest" role = "guest"
} }
@ -278,7 +283,11 @@ func VirtualizationWithContext(ctx context.Context) (string, string, error) {
} }
func GetOSRelease() (platform string, version string, err error) { func GetOSRelease() (platform string, version string, err error) {
contents, err := ReadLines(HostEtc("os-release")) return GetOSReleaseWithContext(context.Background())
}
func GetOSReleaseWithContext(ctx context.Context) (platform string, version string, err error) {
contents, err := ReadLines(HostEtcWithContext(ctx, "os-release"))
if err != nil { if err != nil {
return "", "", nil // return empty return "", "", nil // return empty
} }

@ -1,6 +1,7 @@
package common package common
import ( import (
"context"
"fmt" "fmt"
"os" "os"
"reflect" "reflect"
@ -125,7 +126,7 @@ func TestHostEtc(t *testing.T) {
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
t.Skip("windows doesn't have etc") t.Skip("windows doesn't have etc")
} }
p := HostEtc("mtab") p := HostEtcWithContext(context.Background(), "mtab")
if p != "/etc/mtab" { if p != "/etc/mtab" {
t.Errorf("invalid HostEtc, %s", p) t.Errorf("invalid HostEtc, %s", p)
} }
@ -160,3 +161,44 @@ func TestGetSysctrlEnv(t *testing.T) {
t.Errorf("unexpected real result from getSysctrlEnv: %q", env) t.Errorf("unexpected real result from getSysctrlEnv: %q", env)
} }
} }
func TestGetEnvDefault(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("windows doesn't have etc")
}
p := HostEtcWithContext(context.Background(), "mtab")
if p != "/etc/mtab" {
t.Errorf("invalid HostEtc, %s", p)
}
}
func TestGetEnvWithNoContext(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("windows doesn't have etc")
}
old := os.Getenv("HOST_ETC")
os.Setenv("HOST_ETC", "/bar")
defer func() {
os.Setenv("HOST_ETC", old)
}()
p := HostEtcWithContext(context.Background(), "mtab")
if p != "/bar/mtab" {
t.Errorf("invalid HostEtc, %s", p)
}
}
func TestGetEnvWithContextOverride(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip("windows doesn't have etc")
}
old := os.Getenv("HOST_ETC")
os.Setenv("HOST_ETC", "/bar")
defer func() {
os.Setenv("HOST_ETC", old)
}()
ctx := context.WithValue(context.Background(), Env, map[string]string{"HOST_ETC": "/foo"})
p := HostEtcWithContext(ctx, "mtab")
if p != "/foo/mtab" {
t.Errorf("invalid HostEtc, %s", p)
}
}

@ -18,7 +18,7 @@ func Avg() (*AvgStat, error) {
} }
func AvgWithContext(ctx context.Context) (*AvgStat, error) { func AvgWithContext(ctx context.Context) (*AvgStat, error) {
stat, err := fileAvgWithContext() stat, err := fileAvgWithContext(ctx)
if err != nil { if err != nil {
stat, err = sysinfoAvgWithContext() stat, err = sysinfoAvgWithContext()
} }
@ -40,8 +40,8 @@ func sysinfoAvgWithContext() (*AvgStat, error) {
}, nil }, nil
} }
func fileAvgWithContext() (*AvgStat, error) { func fileAvgWithContext(ctx context.Context) (*AvgStat, error) {
values, err := readLoadAvgFromFile() values, err := readLoadAvgFromFile(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -75,7 +75,7 @@ func Misc() (*MiscStat, error) {
} }
func MiscWithContext(ctx context.Context) (*MiscStat, error) { func MiscWithContext(ctx context.Context) (*MiscStat, error) {
filename := common.HostProc("stat") filename := common.HostProcWithContext(ctx, "stat")
out, err := ioutil.ReadFile(filename) out, err := ioutil.ReadFile(filename)
if err != nil { if err != nil {
return nil, err return nil, err
@ -107,7 +107,7 @@ func MiscWithContext(ctx context.Context) (*MiscStat, error) {
} }
procsTotal, err := getProcsTotal() procsTotal, err := getProcsTotal(ctx)
if err != nil { if err != nil {
return ret, err return ret, err
} }
@ -116,16 +116,16 @@ func MiscWithContext(ctx context.Context) (*MiscStat, error) {
return ret, nil return ret, nil
} }
func getProcsTotal() (int64, error) { func getProcsTotal(ctx context.Context) (int64, error) {
values, err := readLoadAvgFromFile() values, err := readLoadAvgFromFile(ctx)
if err != nil { if err != nil {
return 0, err return 0, err
} }
return strconv.ParseInt(strings.Split(values[3], "/")[1], 10, 64) return strconv.ParseInt(strings.Split(values[3], "/")[1], 10, 64)
} }
func readLoadAvgFromFile() ([]string, error) { func readLoadAvgFromFile(ctx context.Context) ([]string, error) {
loadavgFilename := common.HostProc("loadavg") loadavgFilename := common.HostProcWithContext(ctx, "loadavg")
line, err := ioutil.ReadFile(loadavgFilename) line, err := ioutil.ReadFile(loadavgFilename)
if err != nil { if err != nil {
return nil, err return nil, err

@ -37,7 +37,7 @@ func VirtualMemory() (*VirtualMemoryStat, error) {
} }
func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) { func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) {
vm, _, err := fillFromMeminfoWithContext() vm, _, err := fillFromMeminfoWithContext(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -49,15 +49,15 @@ func VirtualMemoryEx() (*VirtualMemoryExStat, error) {
} }
func VirtualMemoryExWithContext(ctx context.Context) (*VirtualMemoryExStat, error) { func VirtualMemoryExWithContext(ctx context.Context) (*VirtualMemoryExStat, error) {
_, vmEx, err := fillFromMeminfoWithContext() _, vmEx, err := fillFromMeminfoWithContext(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
return vmEx, nil return vmEx, nil
} }
func fillFromMeminfoWithContext() (*VirtualMemoryStat, *VirtualMemoryExStat, error) { func fillFromMeminfoWithContext(ctx context.Context) (*VirtualMemoryStat, *VirtualMemoryExStat, error) {
filename := common.HostProc("meminfo") filename := common.HostProcWithContext(ctx, "meminfo")
lines, _ := common.ReadLines(filename) lines, _ := common.ReadLines(filename)
// flag if MemAvailable is in /proc/meminfo (kernel 3.14+) // flag if MemAvailable is in /proc/meminfo (kernel 3.14+)
@ -318,7 +318,7 @@ func fillFromMeminfoWithContext() (*VirtualMemoryStat, *VirtualMemoryExStat, err
if !memavail { if !memavail {
if activeFile && inactiveFile && sReclaimable { if activeFile && inactiveFile && sReclaimable {
ret.Available = calculateAvailVmem(ret, retEx) ret.Available = calculateAvailVmem(ctx, ret, retEx)
} else { } else {
ret.Available = ret.Cached + ret.Free ret.Available = ret.Cached + ret.Free
} }
@ -351,7 +351,7 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
} else { } else {
ret.UsedPercent = 0 ret.UsedPercent = 0
} }
filename := common.HostProc("vmstat") filename := common.HostProcWithContext(ctx, "vmstat")
lines, _ := common.ReadLines(filename) lines, _ := common.ReadLines(filename)
for _, l := range lines { for _, l := range lines {
fields := strings.Fields(l) fields := strings.Fields(l)
@ -403,10 +403,10 @@ func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) {
// calculateAvailVmem is a fallback under kernel 3.14 where /proc/meminfo does not provide // calculateAvailVmem is a fallback under kernel 3.14 where /proc/meminfo does not provide
// "MemAvailable:" column. It reimplements an algorithm from the link below // "MemAvailable:" column. It reimplements an algorithm from the link below
// https://github.com/giampaolo/psutil/pull/890 // https://github.com/giampaolo/psutil/pull/890
func calculateAvailVmem(ret *VirtualMemoryStat, retEx *VirtualMemoryExStat) uint64 { func calculateAvailVmem(ctx context.Context, ret *VirtualMemoryStat, retEx *VirtualMemoryExStat) uint64 {
var watermarkLow uint64 var watermarkLow uint64
fn := common.HostProc("zoneinfo") fn := common.HostProcWithContext(ctx, "zoneinfo")
lines, err := common.ReadLines(fn) lines, err := common.ReadLines(fn)
if err != nil { if err != nil {
return ret.Free + ret.Cached // fallback under kernel 2.6.13 return ret.Free + ret.Cached // fallback under kernel 2.6.13
@ -458,18 +458,18 @@ func SwapDevices() ([]*SwapDevice, error) {
} }
func SwapDevicesWithContext(ctx context.Context) ([]*SwapDevice, error) { func SwapDevicesWithContext(ctx context.Context) ([]*SwapDevice, error) {
swapsFilePath := common.HostProc(swapsFilename) swapsFilePath := common.HostProcWithContext(ctx, swapsFilename)
f, err := os.Open(swapsFilePath) f, err := os.Open(swapsFilePath)
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer f.Close() defer f.Close()
return parseSwapsFile(f) return parseSwapsFile(ctx, f)
} }
func parseSwapsFile(r io.Reader) ([]*SwapDevice, error) { func parseSwapsFile(ctx context.Context, r io.Reader) ([]*SwapDevice, error) {
swapsFilePath := common.HostProc(swapsFilename) swapsFilePath := common.HostProcWithContext(ctx, swapsFilename)
scanner := bufio.NewScanner(r) scanner := bufio.NewScanner(r)
if !scanner.Scan() { if !scanner.Scan() {
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {

@ -4,6 +4,7 @@
package mem package mem
import ( import (
"context"
"path/filepath" "path/filepath"
"reflect" "reflect"
"strings" "strings"
@ -138,7 +139,7 @@ const invalidFile = `INVALID Type Size Used Priority
func TestParseSwapsFile_ValidFile(t *testing.T) { func TestParseSwapsFile_ValidFile(t *testing.T) {
assert := assert.New(t) assert := assert.New(t)
stats, err := parseSwapsFile(strings.NewReader(validFile)) stats, err := parseSwapsFile(context.Background(), strings.NewReader(validFile))
assert.NoError(err) assert.NoError(err)
assert.Equal(*stats[0], SwapDevice{ assert.Equal(*stats[0], SwapDevice{
@ -155,11 +156,11 @@ func TestParseSwapsFile_ValidFile(t *testing.T) {
} }
func TestParseSwapsFile_InvalidFile(t *testing.T) { func TestParseSwapsFile_InvalidFile(t *testing.T) {
_, err := parseSwapsFile(strings.NewReader(invalidFile)) _, err := parseSwapsFile(context.Background(), strings.NewReader(invalidFile))
assert.Error(t, err) assert.Error(t, err)
} }
func TestParseSwapsFile_EmptyFile(t *testing.T) { func TestParseSwapsFile_EmptyFile(t *testing.T) {
_, err := parseSwapsFile(strings.NewReader("")) _, err := parseSwapsFile(context.Background(), strings.NewReader(""))
assert.Error(t, err) assert.Error(t, err)
} }

@ -50,7 +50,7 @@ func IOCounters(pernic bool) ([]IOCountersStat, error) {
} }
func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) { func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) {
filename := common.HostProc("net/dev") filename := common.HostProcWithContext(ctx, "net/dev")
return IOCountersByFileWithContext(ctx, pernic, filename) return IOCountersByFileWithContext(ctx, pernic, filename)
} }
@ -177,7 +177,7 @@ func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoC
protos[p] = true protos[p] = true
} }
filename := common.HostProc("net/snmp") filename := common.HostProcWithContext(ctx, "net/snmp")
lines, err := common.ReadLines(filename) lines, err := common.ReadLines(filename)
if err != nil { if err != nil {
return nil, err return nil, err
@ -230,8 +230,8 @@ func FilterCounters() ([]FilterStat, error) {
} }
func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) { func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) {
countfile := common.HostProc("sys/net/netfilter/nf_conntrack_count") countfile := common.HostProcWithContext(ctx, "sys/net/netfilter/nf_conntrack_count")
maxfile := common.HostProc("sys/net/netfilter/nf_conntrack_max") maxfile := common.HostProcWithContext(ctx, "sys/net/netfilter/nf_conntrack_max")
count, err := common.ReadInts(countfile) count, err := common.ReadInts(countfile)
if err != nil { if err != nil {
@ -260,7 +260,7 @@ func ConntrackStats(percpu bool) ([]ConntrackStat, error) {
// ConntrackStatsWithContext returns more detailed info about the conntrack table // ConntrackStatsWithContext returns more detailed info about the conntrack table
func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) { func ConntrackStatsWithContext(ctx context.Context, percpu bool) ([]ConntrackStat, error) {
return conntrackStatsFromFile(common.HostProc("net/stat/nf_conntrack"), percpu) return conntrackStatsFromFile(common.HostProcWithContext(ctx, "net/stat/nf_conntrack"), percpu)
} }
// conntrackStatsFromFile returns more detailed info about the conntrack table // conntrackStatsFromFile returns more detailed info about the conntrack table
@ -459,7 +459,7 @@ func connectionsPidMaxWithoutUidsWithContext(ctx context.Context, kind string, p
if !ok { if !ok {
return nil, fmt.Errorf("invalid kind, %s", kind) return nil, fmt.Errorf("invalid kind, %s", kind)
} }
root := common.HostProc() root := common.HostProcWithContext(ctx)
var err error var err error
var inodes map[string][]inodeMap var inodes map[string][]inodeMap
if pid == 0 { if pid == 0 {
@ -531,7 +531,7 @@ func statsFromInodesWithContext(ctx context.Context, root string, pid int32, tma
if !skipUids { if !skipUids {
// fetch process owner Real, effective, saved set, and filesystem UIDs // fetch process owner Real, effective, saved set, and filesystem UIDs
proc := process{Pid: conn.Pid} proc := process{Pid: conn.Pid}
conn.Uids, _ = proc.getUids() conn.Uids, _ = proc.getUids(ctx)
} }
ret = append(ret, conn) ret = append(ret, conn)
@ -599,7 +599,7 @@ func Pids() ([]int32, error) {
func PidsWithContext(ctx context.Context) ([]int32, error) { func PidsWithContext(ctx context.Context) ([]int32, error) {
var ret []int32 var ret []int32
d, err := os.Open(common.HostProc()) d, err := os.Open(common.HostProcWithContext(ctx))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -631,8 +631,8 @@ type process struct {
} }
// Uids returns user ids of the process as a slice of the int // Uids returns user ids of the process as a slice of the int
func (p *process) getUids() ([]int32, error) { func (p *process) getUids(ctx context.Context) ([]int32, error) {
err := p.fillFromStatus() err := p.fillFromStatus(ctx)
if err != nil { if err != nil {
return []int32{}, err return []int32{}, err
} }
@ -640,9 +640,9 @@ func (p *process) getUids() ([]int32, error) {
} }
// Get status from /proc/(pid)/status // Get status from /proc/(pid)/status
func (p *process) fillFromStatus() error { func (p *process) fillFromStatus(ctx context.Context) error {
pid := p.Pid pid := p.Pid
statPath := common.HostProc(strconv.Itoa(int(pid)), "status") statPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "status")
contents, err := ioutil.ReadFile(statPath) contents, err := ioutil.ReadFile(statPath)
if err != nil { if err != nil {
return err return err

@ -1,6 +1,7 @@
package net package net
import ( import (
"context"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net" "net"
@ -101,7 +102,7 @@ func TestGetProcInodesAll(t *testing.T) {
}() }()
<-waitForServer <-waitForServer
root := common.HostProc("") root := common.HostProcWithContext(context.Background(), "")
v, err := getProcInodesAll(root, 0) v, err := getProcInodesAll(root, 0)
assert.Nil(t, err) assert.Nil(t, err)
assert.NotEmpty(t, v) assert.NotEmpty(t, v)

@ -101,7 +101,7 @@ func (p *Process) TgidWithContext(ctx context.Context) (int32, error) {
} }
func (p *Process) ExeWithContext(ctx context.Context) (string, error) { func (p *Process) ExeWithContext(ctx context.Context) (string, error) {
return p.fillFromExeWithContext() return p.fillFromExeWithContext(ctx)
} }
func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) { func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) {
@ -121,7 +121,7 @@ func (p *Process) createTimeWithContext(ctx context.Context) (int64, error) {
} }
func (p *Process) CwdWithContext(ctx context.Context) (string, error) { func (p *Process) CwdWithContext(ctx context.Context) (string, error) {
return p.fillFromCwdWithContext() return p.fillFromCwdWithContext(ctx)
} }
func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) { func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
@ -135,7 +135,7 @@ func (p *Process) StatusWithContext(ctx context.Context) ([]string, error) {
func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) { func (p *Process) ForegroundWithContext(ctx context.Context) (bool, error) {
// see https://github.com/shirou/gopsutil/issues/596#issuecomment-432707831 for implementation details // see https://github.com/shirou/gopsutil/issues/596#issuecomment-432707831 for implementation details
pid := p.Pid pid := p.Pid
statPath := common.HostProc(strconv.Itoa(int(pid)), "stat") statPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "stat")
contents, err := ioutil.ReadFile(statPath) contents, err := ioutil.ReadFile(statPath)
if err != nil { if err != nil {
return false, err return false, err
@ -203,7 +203,7 @@ func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) {
} }
func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) { func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) {
rlimits, err := p.fillFromLimitsWithContext() rlimits, err := p.fillFromLimitsWithContext(ctx)
if !gatherUsed || err != nil { if !gatherUsed || err != nil {
return rlimits, err return rlimits, err
} }
@ -258,7 +258,7 @@ func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) (
} }
func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) { func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) {
return p.fillFromIOWithContext() return p.fillFromIOWithContext(ctx)
} }
func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) { func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) {
@ -284,7 +284,7 @@ func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) {
func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) { func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) {
ret := make(map[int32]*cpu.TimesStat) ret := make(map[int32]*cpu.TimesStat)
taskPath := common.HostProc(strconv.Itoa(int(p.Pid)), "task") taskPath := common.HostProcWithContext(ctx, strconv.Itoa(int(p.Pid)), "task")
tids, err := readPidsFromDir(taskPath) tids, err := readPidsFromDir(taskPath)
if err != nil { if err != nil {
@ -315,7 +315,7 @@ func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) {
} }
func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) { func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) {
meminfo, _, err := p.fillFromStatmWithContext() meminfo, _, err := p.fillFromStatmWithContext(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -323,7 +323,7 @@ func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, e
} }
func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) { func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) {
_, memInfoEx, err := p.fillFromStatmWithContext() _, memInfoEx, err := p.fillFromStatmWithContext(ctx)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -381,12 +381,12 @@ func (p *Process) ConnectionsMaxWithContext(ctx context.Context, max int) ([]net
func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) { func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) {
pid := p.Pid pid := p.Pid
var ret []MemoryMapsStat var ret []MemoryMapsStat
smapsPath := common.HostProc(strconv.Itoa(int(pid)), "smaps") smapsPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "smaps")
if grouped { if grouped {
ret = make([]MemoryMapsStat, 1) ret = make([]MemoryMapsStat, 1)
// If smaps_rollup exists (require kernel >= 4.15), then we will use it // If smaps_rollup exists (require kernel >= 4.15), then we will use it
// for pre-summed memory information for a process. // for pre-summed memory information for a process.
smapsRollupPath := common.HostProc(strconv.Itoa(int(pid)), "smaps_rollup") smapsRollupPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "smaps_rollup")
if _, err := os.Stat(smapsRollupPath); !os.IsNotExist(err) { if _, err := os.Stat(smapsRollupPath); !os.IsNotExist(err) {
smapsPath = smapsRollupPath smapsPath = smapsRollupPath
} }
@ -482,7 +482,7 @@ func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]M
} }
func (p *Process) EnvironWithContext(ctx context.Context) ([]string, error) { func (p *Process) EnvironWithContext(ctx context.Context) ([]string, error) {
environPath := common.HostProc(strconv.Itoa(int(p.Pid)), "environ") environPath := common.HostProcWithContext(ctx, strconv.Itoa(int(p.Pid)), "environ")
environContent, err := ioutil.ReadFile(environPath) environContent, err := ioutil.ReadFile(environPath)
if err != nil { if err != nil {
@ -508,9 +508,9 @@ func limitToUint(val string) (uint64, error) {
} }
// Get num_fds from /proc/(pid)/limits // Get num_fds from /proc/(pid)/limits
func (p *Process) fillFromLimitsWithContext() ([]RlimitStat, error) { func (p *Process) fillFromLimitsWithContext(ctx context.Context) ([]RlimitStat, error) {
pid := p.Pid pid := p.Pid
limitsFile := common.HostProc(strconv.Itoa(int(pid)), "limits") limitsFile := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "limits")
d, err := os.Open(limitsFile) d, err := os.Open(limitsFile)
if err != nil { if err != nil {
return nil, err return nil, err
@ -603,7 +603,7 @@ func (p *Process) fillFromLimitsWithContext() ([]RlimitStat, error) {
// Get list of /proc/(pid)/fd files // Get list of /proc/(pid)/fd files
func (p *Process) fillFromfdListWithContext(ctx context.Context) (string, []string, error) { func (p *Process) fillFromfdListWithContext(ctx context.Context) (string, []string, error) {
pid := p.Pid pid := p.Pid
statPath := common.HostProc(strconv.Itoa(int(pid)), "fd") statPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "fd")
d, err := os.Open(statPath) d, err := os.Open(statPath)
if err != nil { if err != nil {
return statPath, []string{}, err return statPath, []string{}, err
@ -643,9 +643,9 @@ func (p *Process) fillFromfdWithContext(ctx context.Context) (int32, []*OpenFile
} }
// Get cwd from /proc/(pid)/cwd // Get cwd from /proc/(pid)/cwd
func (p *Process) fillFromCwdWithContext() (string, error) { func (p *Process) fillFromCwdWithContext(ctx context.Context) (string, error) {
pid := p.Pid pid := p.Pid
cwdPath := common.HostProc(strconv.Itoa(int(pid)), "cwd") cwdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "cwd")
cwd, err := os.Readlink(cwdPath) cwd, err := os.Readlink(cwdPath)
if err != nil { if err != nil {
return "", err return "", err
@ -654,9 +654,9 @@ func (p *Process) fillFromCwdWithContext() (string, error) {
} }
// Get exe from /proc/(pid)/exe // Get exe from /proc/(pid)/exe
func (p *Process) fillFromExeWithContext() (string, error) { func (p *Process) fillFromExeWithContext(ctx context.Context) (string, error) {
pid := p.Pid pid := p.Pid
exePath := common.HostProc(strconv.Itoa(int(pid)), "exe") exePath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "exe")
exe, err := os.Readlink(exePath) exe, err := os.Readlink(exePath)
if err != nil { if err != nil {
return "", err return "", err
@ -667,7 +667,7 @@ func (p *Process) fillFromExeWithContext() (string, error) {
// Get cmdline from /proc/(pid)/cmdline // Get cmdline from /proc/(pid)/cmdline
func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error) { func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error) {
pid := p.Pid pid := p.Pid
cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline") cmdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "cmdline")
cmdline, err := ioutil.ReadFile(cmdPath) cmdline, err := ioutil.ReadFile(cmdPath)
if err != nil { if err != nil {
return "", err return "", err
@ -681,7 +681,7 @@ func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error
func (p *Process) fillSliceFromCmdlineWithContext(ctx context.Context) ([]string, error) { func (p *Process) fillSliceFromCmdlineWithContext(ctx context.Context) ([]string, error) {
pid := p.Pid pid := p.Pid
cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline") cmdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "cmdline")
cmdline, err := ioutil.ReadFile(cmdPath) cmdline, err := ioutil.ReadFile(cmdPath)
if err != nil { if err != nil {
return nil, err return nil, err
@ -702,9 +702,9 @@ func (p *Process) fillSliceFromCmdlineWithContext(ctx context.Context) ([]string
} }
// Get IO status from /proc/(pid)/io // Get IO status from /proc/(pid)/io
func (p *Process) fillFromIOWithContext() (*IOCountersStat, error) { func (p *Process) fillFromIOWithContext(ctx context.Context) (*IOCountersStat, error) {
pid := p.Pid pid := p.Pid
ioPath := common.HostProc(strconv.Itoa(int(pid)), "io") ioPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "io")
ioline, err := ioutil.ReadFile(ioPath) ioline, err := ioutil.ReadFile(ioPath)
if err != nil { if err != nil {
return nil, err return nil, err
@ -738,9 +738,9 @@ func (p *Process) fillFromIOWithContext() (*IOCountersStat, error) {
} }
// Get memory info from /proc/(pid)/statm // Get memory info from /proc/(pid)/statm
func (p *Process) fillFromStatmWithContext() (*MemoryInfoStat, *MemoryInfoExStat, error) { func (p *Process) fillFromStatmWithContext(ctx context.Context) (*MemoryInfoStat, *MemoryInfoExStat, error) {
pid := p.Pid pid := p.Pid
memPath := common.HostProc(strconv.Itoa(int(pid)), "statm") memPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "statm")
contents, err := ioutil.ReadFile(memPath) contents, err := ioutil.ReadFile(memPath)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@ -791,7 +791,7 @@ func (p *Process) fillFromStatmWithContext() (*MemoryInfoStat, *MemoryInfoExStat
// Get name from /proc/(pid)/comm or /proc/(pid)/status // Get name from /proc/(pid)/comm or /proc/(pid)/status
func (p *Process) fillNameWithContext(ctx context.Context) error { func (p *Process) fillNameWithContext(ctx context.Context) error {
err := p.fillFromCommWithContext() err := p.fillFromCommWithContext(ctx)
if err == nil && p.name != "" && len(p.name) < 15 { if err == nil && p.name != "" && len(p.name) < 15 {
return nil return nil
} }
@ -799,9 +799,9 @@ func (p *Process) fillNameWithContext(ctx context.Context) error {
} }
// Get name from /proc/(pid)/comm // Get name from /proc/(pid)/comm
func (p *Process) fillFromCommWithContext() error { func (p *Process) fillFromCommWithContext(ctx context.Context) error {
pid := p.Pid pid := p.Pid
statPath := common.HostProc(strconv.Itoa(int(pid)), "comm") statPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "comm")
contents, err := ioutil.ReadFile(statPath) contents, err := ioutil.ReadFile(statPath)
if err != nil { if err != nil {
return err return err
@ -818,7 +818,7 @@ func (p *Process) fillFromStatus() error {
func (p *Process) fillFromStatusWithContext(ctx context.Context) error { func (p *Process) fillFromStatusWithContext(ctx context.Context) error {
pid := p.Pid pid := p.Pid
statPath := common.HostProc(strconv.Itoa(int(pid)), "status") statPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "status")
contents, err := ioutil.ReadFile(statPath) contents, err := ioutil.ReadFile(statPath)
if err != nil { if err != nil {
return err return err
@ -1023,9 +1023,9 @@ func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (ui
var statPath string var statPath string
if tid == -1 { if tid == -1 {
statPath = common.HostProc(strconv.Itoa(int(pid)), "stat") statPath = common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "stat")
} else { } else {
statPath = common.HostProc(strconv.Itoa(int(pid)), "task", strconv.Itoa(int(tid)), "stat") statPath = common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "task", strconv.Itoa(int(tid)), "stat")
} }
contents, err := ioutil.ReadFile(statPath) contents, err := ioutil.ReadFile(statPath)
@ -1129,7 +1129,7 @@ func (p *Process) fillFromStatWithContext(ctx context.Context) (uint64, int32, *
} }
func pidsWithContext(ctx context.Context) ([]int32, error) { func pidsWithContext(ctx context.Context) ([]int32, error) {
return readPidsFromDir(common.HostProc()) return readPidsFromDir(common.HostProcWithContext(ctx))
} }
func ProcessesWithContext(ctx context.Context) ([]*Process, error) { func ProcessesWithContext(ctx context.Context) ([]*Process, error) {

@ -4,6 +4,7 @@
package process package process
import ( import (
"context"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
@ -107,7 +108,7 @@ func Test_fillFromCommWithContext(t *testing.T) {
continue continue
} }
p, _ := NewProcess(int32(pid)) p, _ := NewProcess(int32(pid))
if err := p.fillFromCommWithContext(); err != nil { if err := p.fillFromCommWithContext(context.Background()); err != nil {
t.Error(err) t.Error(err)
} }
} }
@ -139,7 +140,7 @@ func Benchmark_fillFromCommWithContext(b *testing.B) {
pid := 1060 pid := 1060
p, _ := NewProcess(int32(pid)) p, _ := NewProcess(int32(pid))
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
p.fillFromCommWithContext() p.fillFromCommWithContext(context.Background())
} }
} }

@ -109,8 +109,8 @@ func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) {
return false, err return false, err
} }
if isMount(common.HostProc()) { // if /<HOST_PROC>/proc exists and is mounted, check if /<HOST_PROC>/proc/<PID> folder exists if isMount(common.HostProcWithContext(ctx)) { // if /<HOST_PROC>/proc exists and is mounted, check if /<HOST_PROC>/proc/<PID> folder exists
_, err := os.Stat(common.HostProc(strconv.Itoa(int(pid)))) _, err := os.Stat(common.HostProcWithContext(ctx, strconv.Itoa(int(pid))))
if os.IsNotExist(err) { if os.IsNotExist(err) {
return false, nil return false, nil
} }

@ -30,7 +30,7 @@ type MemoryMapsStat struct {
type MemoryInfoExStat struct{} type MemoryInfoExStat struct{}
func pidsWithContext(ctx context.Context) ([]int32, error) { func pidsWithContext(ctx context.Context) ([]int32, error) {
return readPidsFromDir(common.HostProc()) return readPidsFromDir(common.HostProcWithContext(ctx))
} }
func ProcessesWithContext(ctx context.Context) ([]*Process, error) { func ProcessesWithContext(ctx context.Context) ([]*Process, error) {
@ -199,7 +199,7 @@ func (p *Process) EnvironWithContext(ctx context.Context) ([]string, error) {
func (p *Process) fillFromfdListWithContext(ctx context.Context) (string, []string, error) { func (p *Process) fillFromfdListWithContext(ctx context.Context) (string, []string, error) {
pid := p.Pid pid := p.Pid
statPath := common.HostProc(strconv.Itoa(int(pid)), "fd") statPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "fd")
d, err := os.Open(statPath) d, err := os.Open(statPath)
if err != nil { if err != nil {
return statPath, []string{}, err return statPath, []string{}, err
@ -211,7 +211,7 @@ func (p *Process) fillFromfdListWithContext(ctx context.Context) (string, []stri
func (p *Process) fillFromPathCwdWithContext(ctx context.Context) (string, error) { func (p *Process) fillFromPathCwdWithContext(ctx context.Context) (string, error) {
pid := p.Pid pid := p.Pid
cwdPath := common.HostProc(strconv.Itoa(int(pid)), "path", "cwd") cwdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "path", "cwd")
cwd, err := os.Readlink(cwdPath) cwd, err := os.Readlink(cwdPath)
if err != nil { if err != nil {
return "", err return "", err
@ -221,7 +221,7 @@ func (p *Process) fillFromPathCwdWithContext(ctx context.Context) (string, error
func (p *Process) fillFromPathAOutWithContext(ctx context.Context) (string, error) { func (p *Process) fillFromPathAOutWithContext(ctx context.Context) (string, error) {
pid := p.Pid pid := p.Pid
cwdPath := common.HostProc(strconv.Itoa(int(pid)), "path", "a.out") cwdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "path", "a.out")
exe, err := os.Readlink(cwdPath) exe, err := os.Readlink(cwdPath)
if err != nil { if err != nil {
return "", err return "", err
@ -231,7 +231,7 @@ func (p *Process) fillFromPathAOutWithContext(ctx context.Context) (string, erro
func (p *Process) fillFromExecnameWithContext(ctx context.Context) (string, error) { func (p *Process) fillFromExecnameWithContext(ctx context.Context) (string, error) {
pid := p.Pid pid := p.Pid
execNamePath := common.HostProc(strconv.Itoa(int(pid)), "execname") execNamePath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "execname")
exe, err := ioutil.ReadFile(execNamePath) exe, err := ioutil.ReadFile(execNamePath)
if err != nil { if err != nil {
return "", err return "", err
@ -241,7 +241,7 @@ func (p *Process) fillFromExecnameWithContext(ctx context.Context) (string, erro
func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error) { func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error) {
pid := p.Pid pid := p.Pid
cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline") cmdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "cmdline")
cmdline, err := ioutil.ReadFile(cmdPath) cmdline, err := ioutil.ReadFile(cmdPath)
if err != nil { if err != nil {
return "", err return "", err
@ -258,7 +258,7 @@ func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error
func (p *Process) fillSliceFromCmdlineWithContext(ctx context.Context) ([]string, error) { func (p *Process) fillSliceFromCmdlineWithContext(ctx context.Context) ([]string, error) {
pid := p.Pid pid := p.Pid
cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline") cmdPath := common.HostProcWithContext(ctx, strconv.Itoa(int(pid)), "cmdline")
cmdline, err := ioutil.ReadFile(cmdPath) cmdline, err := ioutil.ReadFile(cmdPath)
if err != nil { if err != nil {
return nil, err return nil, err

Loading…
Cancel
Save