From 4c73494c780fd9b46c1ce1953907d436516a3ce0 Mon Sep 17 00:00:00 2001 From: shirou Date: Sun, 31 Dec 2017 15:25:49 +0900 Subject: [PATCH 1/2] Add WithContext functions. --- Makefile | 2 +- cpu/cpu.go | 9 +++ cpu/cpu_darwin.go | 9 +++ cpu/cpu_fallback.go | 10 +++ cpu/cpu_freebsd.go | 9 +++ cpu/cpu_linux.go | 9 +++ cpu/cpu_openbsd.go | 9 +++ cpu/cpu_solaris.go | 9 +++ cpu/cpu_windows.go | 16 ++++ disk/disk_darwin.go | 9 +++ disk/disk_darwin_cgo.go | 5 ++ disk/disk_darwin_nocgo.go | 10 ++- disk/disk_fallback.go | 18 ++++- disk/disk_freebsd.go | 13 ++++ disk/disk_linux.go | 13 ++++ disk/disk_openbsd.go | 17 +++++ disk/disk_solaris.go | 127 +++++++++++++++++++++++++++++++ disk/disk_unix.go | 10 ++- disk/disk_windows.go | 12 +++ docker/docker_linux.go | 25 +++++++ docker/docker_notlinux.go | 25 +++++++ host/host_darwin.go | 29 ++++++++ host/host_darwin_cgo.go | 5 ++ host/host_darwin_nocgo.go | 10 ++- host/host_fallback.go | 30 +++++++- host/host_freebsd.go | 33 +++++++++ host/host_linux.go | 33 +++++++++ host/host_openbsd.go | 33 +++++++++ host/host_solaris.go | 29 ++++++++ host/host_windows.go | 36 +++++++++ load/load_bsd.go | 9 +++ load/load_darwin.go | 9 +++ load/load_fallback.go | 14 +++- load/load_linux.go | 9 +++ load/load_windows.go | 10 +++ mem/mem_darwin.go | 5 ++ mem/mem_darwin_cgo.go | 5 ++ mem/mem_darwin_nocgo.go | 5 ++ mem/mem_fallback.go | 14 +++- mem/mem_freebsd.go | 9 +++ mem/mem_linux.go | 9 +++ mem/mem_openbsd.go | 16 +++- mem/mem_solaris.go | 9 +++ mem/mem_windows.go | 46 +++++++----- net/net.go | 5 ++ net/net_darwin.go | 17 +++++ net/net_fallback.go | 26 ++++++- net/net_freebsd.go | 17 +++++ net/net_linux.go | 41 ++++++++++ net/net_openbsd.go | 21 ++++++ net/net_unix.go | 17 +++++ net/net_windows.go | 25 +++++++ process/process.go | 17 +++++ process/process_darwin.go | 135 ++++++++++++++++++++++++++++++++- process/process_fallback.go | 155 +++++++++++++++++++++++++++++++++++++- process/process_freebsd.go | 135 ++++++++++++++++++++++++++++++++- process/process_linux.go | 177 ++++++++++++++++++++++++++++++++++++++++++++ process/process_openbsd.go | 139 +++++++++++++++++++++++++++++++++- process/process_posix.go | 25 +++++++ process/process_windows.go | 158 ++++++++++++++++++++++++++++++++++++++- 60 files changed, 1849 insertions(+), 34 deletions(-) create mode 100644 disk/disk_solaris.go diff --git a/Makefile b/Makefile index dbe306a..cd75f78 100644 --- a/Makefile +++ b/Makefile @@ -17,10 +17,10 @@ build_test: ## test only buildable GOOS=freebsd go test ./... | $(BUILD_FAIL_PATTERN) # GOOS=openbsd go test ./... | $(BUILD_FAIL_PATTERN) CGO_ENABLED=0 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN) - CGO_ENABLED=1 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN) GOOS=windows go test ./... | $(BUILD_FAIL_PATTERN) # Operating systems supported for building only (not implemented error if used) GOOS=solaris go test ./... | $(BUILD_FAIL_PATTERN) # GOOS=dragonfly go test ./... | $(BUILD_FAIL_PATTERN) GOOS=netbsd go test ./... | $(BUILD_FAIL_PATTERN) + CGO_ENABLED=1 GOOS=darwin go test ./... | $(BUILD_FAIL_PATTERN) @echo 'Successfully built on all known operating systems' diff --git a/cpu/cpu.go b/cpu/cpu.go index f0dccd4..049869e 100644 --- a/cpu/cpu.go +++ b/cpu/cpu.go @@ -1,6 +1,7 @@ package cpu import ( + "context" "encoding/json" "fmt" "runtime" @@ -64,6 +65,10 @@ func init() { } func Counts(logical bool) (int, error) { + return CountsWithContext(context.Background(), logical) +} + +func CountsWithContext(ctx context.Context, logical bool) (int, error) { return runtime.NumCPU(), nil } @@ -137,6 +142,10 @@ func calculateAllBusy(t1, t2 []TimesStat) ([]float64, error) { // If an interval of 0 is given it will compare the current cpu times against the last call. // Returns one value per cpu, or a single value if percpu is set to false. func Percent(interval time.Duration, percpu bool) ([]float64, error) { + return PercentWithContext(context.Background(), interval, percpu) +} + +func PercentWithContext(ctx context.Context, interval time.Duration, percpu bool) ([]float64, error) { if interval <= 0 { return percentUsedFromLastCall(percpu) } diff --git a/cpu/cpu_darwin.go b/cpu/cpu_darwin.go index af27e62..001517e 100644 --- a/cpu/cpu_darwin.go +++ b/cpu/cpu_darwin.go @@ -3,6 +3,7 @@ package cpu import ( + "context" "os/exec" "strconv" "strings" @@ -22,6 +23,10 @@ const ( var ClocksPerSec = float64(128) func Times(percpu bool) ([]TimesStat, error) { + return TimesWithContext(context.Background(), percpu) +} + +func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { if percpu { return perCPUTimes() } @@ -31,6 +36,10 @@ func Times(percpu bool) ([]TimesStat, error) { // Returns only one CPUInfoStat on FreeBSD func Info() ([]InfoStat, error) { + return InfoWithContext(context.Background()) +} + +func InfoWithContext(ctx context.Context) ([]InfoStat, error) { var ret []InfoStat sysctl, err := exec.LookPath("/usr/sbin/sysctl") if err != nil { diff --git a/cpu/cpu_fallback.go b/cpu/cpu_fallback.go index 8e09ccb..e9e7ada 100644 --- a/cpu/cpu_fallback.go +++ b/cpu/cpu_fallback.go @@ -3,13 +3,23 @@ package cpu import ( + "context" + "github.com/shirou/gopsutil/internal/common" ) func Times(percpu bool) ([]TimesStat, error) { + return TimesWithContext(context.Background(), percpu) +} + +func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { return []TimesStat{}, common.ErrNotImplementedError } func Info() ([]InfoStat, error) { + return InfoWithContext(context.Background()) +} + +func InfoWithContext(ctx context.Context) ([]InfoStat, error) { return []InfoStat{}, common.ErrNotImplementedError } diff --git a/cpu/cpu_freebsd.go b/cpu/cpu_freebsd.go index a6d7847..b6c7186 100644 --- a/cpu/cpu_freebsd.go +++ b/cpu/cpu_freebsd.go @@ -1,6 +1,7 @@ package cpu import ( + "context" "fmt" "os/exec" "reflect" @@ -50,6 +51,10 @@ func timeStat(name string, t *cpuTimes) *TimesStat { } func Times(percpu bool) ([]TimesStat, error) { + return TimesWithContext(context.Background(), percpu) +} + +func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { if percpu { buf, err := unix.SysctlRaw("kern.cp_times") if err != nil { @@ -87,6 +92,10 @@ func Times(percpu bool) ([]TimesStat, error) { // count, however is accurate and it is assumed that all InfoStat attributes // are the same across CPUs. func Info() ([]InfoStat, error) { + return InfoWithContext(context.Background()) +} + +func InfoWithContext(ctx context.Context) ([]InfoStat, error) { const dmesgBoot = "/var/run/dmesg.boot" c, num, err := parseDmesgBoot(dmesgBoot) diff --git a/cpu/cpu_linux.go b/cpu/cpu_linux.go index 48e45da..0f3d928 100644 --- a/cpu/cpu_linux.go +++ b/cpu/cpu_linux.go @@ -3,6 +3,7 @@ package cpu import ( + "context" "errors" "fmt" "os/exec" @@ -30,6 +31,10 @@ func init() { } func Times(percpu bool) ([]TimesStat, error) { + return TimesWithContext(context.Background(), percpu) +} + +func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { filename := common.HostProc("stat") var lines = []string{} if percpu { @@ -104,6 +109,10 @@ func finishCPUInfo(c *InfoStat) error { // For example a single socket board with two cores each with HT will // return 4 CPUInfoStat structs on Linux and the "Cores" field set to 1. func Info() ([]InfoStat, error) { + return InfoWithContext(context.Background()) +} + +func InfoWithContext(ctx context.Context) ([]InfoStat, error) { filename := common.HostProc("cpuinfo") lines, _ := common.ReadLines(filename) diff --git a/cpu/cpu_openbsd.go b/cpu/cpu_openbsd.go index 03aae6e..82b920f 100644 --- a/cpu/cpu_openbsd.go +++ b/cpu/cpu_openbsd.go @@ -4,6 +4,7 @@ package cpu import ( "bytes" + "context" "encoding/binary" "fmt" "os/exec" @@ -49,6 +50,10 @@ func init() { } func Times(percpu bool) ([]TimesStat, error) { + return TimesWithContext(context.Background(), percpu) +} + +func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { var ret []TimesStat var ncpu int @@ -96,6 +101,10 @@ func Times(percpu bool) ([]TimesStat, error) { // Returns only one (minimal) CPUInfoStat on OpenBSD func Info() ([]InfoStat, error) { + return InfoWithContext(context.Background()) +} + +func InfoWithContext(ctx context.Context) ([]InfoStat, error) { var ret []InfoStat c := InfoStat{} diff --git a/cpu/cpu_solaris.go b/cpu/cpu_solaris.go index b56786b..0899f41 100644 --- a/cpu/cpu_solaris.go +++ b/cpu/cpu_solaris.go @@ -1,6 +1,7 @@ package cpu import ( + "context" "errors" "fmt" "os/exec" @@ -30,10 +31,18 @@ func init() { } func Times(percpu bool) ([]TimesStat, error) { + return TimesWithContext(context.Background(), percpu) +} + +func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { return []TimesStat{}, common.ErrNotImplementedError } func Info() ([]InfoStat, error) { + return InfoWithContext(context.Background()) +} + +func InfoWithContext(ctx context.Context) ([]InfoStat, error) { psrInfo, err := exec.LookPath("/usr/sbin/psrinfo") if err != nil { return nil, fmt.Errorf("cannot find psrinfo: %s", err) diff --git a/cpu/cpu_windows.go b/cpu/cpu_windows.go index b012fde..af65721 100644 --- a/cpu/cpu_windows.go +++ b/cpu/cpu_windows.go @@ -46,6 +46,10 @@ type Win32_PerfFormattedData_PerfOS_System struct { // Times returns times stat per cpu and combined for all CPUs func Times(percpu bool) ([]TimesStat, error) { + return TimesWithContext(context.Background(), percpu) +} + +func TimesWithContext(ctx context.Context, percpu bool) ([]TimesStat, error) { if percpu { return perCPUTimes() } @@ -79,6 +83,10 @@ func Times(percpu bool) ([]TimesStat, error) { } func Info() ([]InfoStat, error) { + return InfoWithContext(context.Background()) +} + +func InfoWithContext(ctx context.Context) ([]InfoStat, error) { var ret []InfoStat var dst []Win32_Processor q := wmi.CreateQuery(&dst, "") @@ -114,6 +122,10 @@ func Info() ([]InfoStat, error) { // PerfInfo returns the performance counter's instance value for ProcessorInformation. // Name property is the key by which overall, per cpu and per core metric is known. func PerfInfo() ([]Win32_PerfFormattedData_Counters_ProcessorInformation, error) { + return PerfInfoWithContext(context.Background()) +} + +func PerfInfoWithContext(ctx context.Context) ([]Win32_PerfFormattedData_Counters_ProcessorInformation, error) { var ret []Win32_PerfFormattedData_Counters_ProcessorInformation q := wmi.CreateQuery(&ret, "") @@ -126,6 +138,10 @@ func PerfInfo() ([]Win32_PerfFormattedData_Counters_ProcessorInformation, error) // ProcInfo returns processes count and processor queue length in the system. // There is a single queue for processor even on multiprocessors systems. func ProcInfo() ([]Win32_PerfFormattedData_PerfOS_System, error) { + return ProcInfoWithContext(context.Background()) +} + +func ProcInfoWithContext(ctx context.Context) ([]Win32_PerfFormattedData_PerfOS_System, error) { var ret []Win32_PerfFormattedData_PerfOS_System q := wmi.CreateQuery(&ret, "") ctx, cancel := context.WithTimeout(context.Background(), common.Timeout) diff --git a/disk/disk_darwin.go b/disk/disk_darwin.go index 76672c1..82ffacb 100644 --- a/disk/disk_darwin.go +++ b/disk/disk_darwin.go @@ -3,6 +3,7 @@ package disk import ( + "context" "path" "unsafe" @@ -11,6 +12,10 @@ import ( ) func Partitions(all bool) ([]PartitionStat, error) { + return PartitionsWithContext(context.Background(), all) +} + +func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) { var ret []PartitionStat count, err := Getfsstat(nil, MntWait) @@ -88,6 +93,10 @@ func Partitions(all bool) ([]PartitionStat, error) { } func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { + return GetfsstatWithContext(context.Background(), buf, flags) +} + +func GetfsstatWithContext(ctx context.Context, buf []Statfs_t, flags int) (n int, err error) { var _p0 unsafe.Pointer var bufsize uintptr if len(buf) > 0 { diff --git a/disk/disk_darwin_cgo.go b/disk/disk_darwin_cgo.go index f75ac9b..480e237 100644 --- a/disk/disk_darwin_cgo.go +++ b/disk/disk_darwin_cgo.go @@ -26,6 +26,7 @@ typedef struct import "C" import ( + "context" "errors" "strings" "unsafe" @@ -34,6 +35,10 @@ import ( ) func IOCounters(names ...string) (map[string]IOCountersStat, error) { + return IOCountersWithContext(context.Background(), names...) +} + +func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) { if C.StartIOCounterFetch() == 0 { return nil, errors.New("Unable to fetch disk list") } diff --git a/disk/disk_darwin_nocgo.go b/disk/disk_darwin_nocgo.go index 60fd7a6..fe76d83 100644 --- a/disk/disk_darwin_nocgo.go +++ b/disk/disk_darwin_nocgo.go @@ -3,8 +3,16 @@ package disk -import "github.com/shirou/gopsutil/internal/common" +import ( + "context" + + "github.com/shirou/gopsutil/internal/common" +) func IOCounters(names ...string) (map[string]IOCountersStat, error) { + return IOCountersWithContext(context.Background(), names...) +} + +func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) { return nil, common.ErrNotImplementedError } diff --git a/disk/disk_fallback.go b/disk/disk_fallback.go index ae9ffa8..22eb507 100644 --- a/disk/disk_fallback.go +++ b/disk/disk_fallback.go @@ -2,16 +2,32 @@ package disk -import "github.com/shirou/gopsutil/internal/common" +import ( + "context" + + "github.com/shirou/gopsutil/internal/common" +) func IOCounters(names ...string) (map[string]IOCountersStat, error) { + return IOCountersWithContext(context.Background(), names...) +} + +func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) { return nil, common.ErrNotImplementedError } func Partitions(all bool) ([]PartitionStat, error) { + return PartitionsWithContext(context.Background(), all) +} + +func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) { return []PartitionStat{}, common.ErrNotImplementedError } func Usage(path string) (*UsageStat, error) { + return UsageWithContext(context.Background(), path) +} + +func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) { return nil, common.ErrNotImplementedError } diff --git a/disk/disk_freebsd.go b/disk/disk_freebsd.go index 8cd5aef..bfb6580 100644 --- a/disk/disk_freebsd.go +++ b/disk/disk_freebsd.go @@ -4,6 +4,7 @@ package disk import ( "bytes" + "context" "encoding/binary" "path" "strconv" @@ -15,6 +16,10 @@ import ( ) func Partitions(all bool) ([]PartitionStat, error) { + return PartitionsWithContext(context.Background(), all) +} + +func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) { var ret []PartitionStat // get length @@ -96,6 +101,10 @@ func Partitions(all bool) ([]PartitionStat, error) { } func IOCounters(names ...string) (map[string]IOCountersStat, error) { + return IOCountersWithContext(context.Background(), names...) +} + +func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) { // statinfo->devinfo->devstat // /usr/include/devinfo.h ret := make(map[string]IOCountersStat) @@ -150,6 +159,10 @@ func (b Bintime) Compute() float64 { // Getfsstat is borrowed from pkg/syscall/syscall_freebsd.go // change Statfs_t to Statfs in order to get more information func Getfsstat(buf []Statfs, flags int) (n int, err error) { + return GetfsstatWithContext(context.Background(), buf, flags) +} + +func GetfsstatWithContext(ctx context.Context, buf []Statfs, flags int) (n int, err error) { var _p0 unsafe.Pointer var bufsize uintptr if len(buf) > 0 { diff --git a/disk/disk_linux.go b/disk/disk_linux.go index f31c391..0bc6e2f 100644 --- a/disk/disk_linux.go +++ b/disk/disk_linux.go @@ -3,6 +3,7 @@ package disk import ( + "context" "fmt" "os/exec" "strconv" @@ -216,6 +217,10 @@ var fsTypeMap = map[int64]string{ // physical devices only (e.g. hard disks, cd-rom drives, USB keys) // and ignore all others (e.g. memory partitions such as /dev/shm) func Partitions(all bool) ([]PartitionStat, error) { + return PartitionsWithContext(context.Background(), all) +} + +func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) { filename := common.HostProc("self/mounts") lines, err := common.ReadLines(filename) if err != nil { @@ -272,6 +277,10 @@ func getFileSystems() ([]string, error) { } func IOCounters(names ...string) (map[string]IOCountersStat, error) { + return IOCountersWithContext(context.Background(), names...) +} + +func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) { filename := common.HostProc("diskstats") lines, err := common.ReadLines(filename) if err != nil { @@ -363,6 +372,10 @@ func IOCounters(names ...string) (map[string]IOCountersStat, error) { // GetDiskSerialNumber returns Serial Number of given device or empty string // on error. Name of device is expected, eg. /dev/sda func GetDiskSerialNumber(name string) string { + return GetDiskSerialNumberWithContext(context.Background(), name) +} + +func GetDiskSerialNumberWithContext(ctx context.Context, name string) string { n := fmt.Sprintf("--name=%s", name) udevadm, err := exec.LookPath("/sbin/udevadm") if err != nil { diff --git a/disk/disk_openbsd.go b/disk/disk_openbsd.go index 348a1f1..0ac752a 100644 --- a/disk/disk_openbsd.go +++ b/disk/disk_openbsd.go @@ -4,6 +4,7 @@ package disk import ( "bytes" + "context" "encoding/binary" "path" "unsafe" @@ -13,6 +14,10 @@ import ( ) func Partitions(all bool) ([]PartitionStat, error) { + return PartitionsWithContext(context.Background(), all) +} + +func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) { var ret []PartitionStat // get length @@ -64,6 +69,10 @@ func Partitions(all bool) ([]PartitionStat, error) { } func IOCounters(names ...string) (map[string]IOCountersStat, error) { + return IOCountersWithContext(context.Background(), names...) +} + +func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) { ret := make(map[string]IOCountersStat) r, err := unix.SysctlRaw("hw.diskstats") @@ -106,6 +115,10 @@ func IOCounters(names ...string) (map[string]IOCountersStat, error) { // Getfsstat is borrowed from pkg/syscall/syscall_freebsd.go // change Statfs_t to Statfs in order to get more information func Getfsstat(buf []Statfs, flags int) (n int, err error) { + return GetfsstatWithContext(context.Background(), buf, flags) +} + +func GetfsstatWithContext(ctx context.Context, buf []Statfs, flags int) (n int, err error) { var _p0 unsafe.Pointer var bufsize uintptr if len(buf) > 0 { @@ -133,6 +146,10 @@ func parseDiskstats(buf []byte) (Diskstats, error) { } func Usage(path string) (*UsageStat, error) { + return UsageWithContext(context.Background(), path) +} + +func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) { stat := unix.Statfs_t{} err := unix.Statfs(path, &stat) if err != nil { diff --git a/disk/disk_solaris.go b/disk/disk_solaris.go new file mode 100644 index 0000000..c660835 --- /dev/null +++ b/disk/disk_solaris.go @@ -0,0 +1,127 @@ +// +build solaris + +package disk + +import ( + "bufio" + "context" + "fmt" + "math" + "os" + "strings" + + "github.com/shirou/gopsutil/internal/common" + "golang.org/x/sys/unix" +) + +const ( + // _DEFAULT_NUM_MOUNTS is set to `cat /etc/mnttab | wc -l` rounded up to the + // nearest power of two. + _DEFAULT_NUM_MOUNTS = 32 + + // _MNTTAB default place to read mount information + _MNTTAB = "/etc/mnttab" +) + +var ( + // A blacklist of read-only virtual filesystems. Writable filesystems are of + // operational concern and must not be included in this list. + fsTypeBlacklist = map[string]struct{}{ + "ctfs": struct{}{}, + "dev": struct{}{}, + "fd": struct{}{}, + "lofs": struct{}{}, + "lxproc": struct{}{}, + "mntfs": struct{}{}, + "objfs": struct{}{}, + "proc": struct{}{}, + } +) + +func Partitions(all bool) ([]PartitionStat, error) { + return PartitionsWithContext(context.Background(), all) +} + +func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) { + ret := make([]PartitionStat, 0, _DEFAULT_NUM_MOUNTS) + + // Scan mnttab(4) + f, err := os.Open(_MNTTAB) + if err != nil { + } + defer func() { + if err == nil { + err = f.Close() + } else { + f.Close() + } + }() + + scanner := bufio.NewScanner(f) + for scanner.Scan() { + fields := strings.Split(scanner.Text(), "\t") + + if _, found := fsTypeBlacklist[fields[2]]; found { + continue + } + + ret = append(ret, PartitionStat{ + // NOTE(seanc@): Device isn't exactly accurate: from mnttab(4): "The name + // of the resource that has been mounted." Ideally this value would come + // from Statvfs_t.Fsid but I'm leaving it to the caller to traverse + // unix.Statvfs(). + Device: fields[0], + Mountpoint: fields[1], + Fstype: fields[2], + Opts: fields[3], + }) + } + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("unable to scan %q: %v", _MNTTAB, err) + } + + return ret, err +} + +func IOCounters(names ...string) (map[string]IOCountersStat, error) { + return IOCountersWithContext(context.Background(), names...) +} + +func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) { + return nil, common.ErrNotImplementedError +} + +func Usage(path string) (*UsageStat, error) { + return UsageWithContext(context.Background(), path) +} + +func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) { + statvfs := unix.Statvfs_t{} + if err := unix.Statvfs(path, &statvfs); err != nil { + return nil, fmt.Errorf("unable to call statvfs(2) on %q: %v", path, err) + } + + usageStat := &UsageStat{ + Path: path, + Fstype: common.IntToString(statvfs.Basetype[:]), + Total: statvfs.Blocks * statvfs.Frsize, + Free: statvfs.Bfree * statvfs.Frsize, + Used: (statvfs.Blocks - statvfs.Bfree) * statvfs.Frsize, + + // NOTE: ZFS (and FreeBZSD's UFS2) use dynamic inode/dnode allocation. + // Explicitly return a near-zero value for InodesUsedPercent so that nothing + // attempts to garbage collect based on a lack of available inodes/dnodes. + // Similarly, don't use the zero value to prevent divide-by-zero situations + // and inject a faux near-zero value. Filesystems evolve. Has your + // filesystem evolved? Probably not if you care about the number of + // available inodes. + InodesTotal: 1024.0 * 1024.0, + InodesUsed: 1024.0, + InodesFree: math.MaxUint64, + InodesUsedPercent: (1024.0 / (1024.0 * 1024.0)) * 100.0, + } + + usageStat.UsedPercent = (float64(usageStat.Used) / float64(usageStat.Total)) * 100.0 + + return usageStat, nil +} diff --git a/disk/disk_unix.go b/disk/disk_unix.go index 8520829..bafef51 100644 --- a/disk/disk_unix.go +++ b/disk/disk_unix.go @@ -2,12 +2,20 @@ package disk -import "golang.org/x/sys/unix" +import ( + "context" + + "golang.org/x/sys/unix" +) // Usage returns a file system usage. path is a filessytem path such // as "/", not device file path like "/dev/vda1". If you want to use // a return value of disk.Partitions, use "Mountpoint" not "Device". func Usage(path string) (*UsageStat, error) { + return UsageWithContext(context.Background(), path) +} + +func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) { stat := unix.Statfs_t{} err := unix.Statfs(path, &stat) if err != nil { diff --git a/disk/disk_windows.go b/disk/disk_windows.go index 9e5f681..7389b5a 100644 --- a/disk/disk_windows.go +++ b/disk/disk_windows.go @@ -36,6 +36,10 @@ type Win32_PerfFormattedData struct { const WaitMSec = 500 func Usage(path string) (*UsageStat, error) { + return UsageWithContext(context.Background(), path) +} + +func UsageWithContext(ctx context.Context, path string) (*UsageStat, error) { ret := &UsageStat{} lpFreeBytesAvailable := int64(0) @@ -64,6 +68,10 @@ func Usage(path string) (*UsageStat, error) { } func Partitions(all bool) ([]PartitionStat, error) { + return PartitionsWithContext(context.Background(), all) +} + +func PartitionsWithContext(ctx context.Context, all bool) ([]PartitionStat, error) { var ret []PartitionStat lpBuffer := make([]byte, 254) diskret, _, err := procGetLogicalDriveStringsW.Call( @@ -129,6 +137,10 @@ func Partitions(all bool) ([]PartitionStat, error) { } func IOCounters(names ...string) (map[string]IOCountersStat, error) { + return IOCountersWithContext(context.Background(), names...) +} + +func IOCountersWithContext(ctx context.Context, names ...string) (map[string]IOCountersStat, error) { ret := make(map[string]IOCountersStat, 0) var dst []Win32_PerfFormattedData diff --git a/docker/docker_linux.go b/docker/docker_linux.go index 000d2f2..8c722a0 100644 --- a/docker/docker_linux.go +++ b/docker/docker_linux.go @@ -3,6 +3,7 @@ package docker import ( + "context" "encoding/json" "fmt" "os" @@ -18,6 +19,10 @@ import ( // GetDockerStat returns a list of Docker basic stats. // This requires certain permission. func GetDockerStat() ([]CgroupDockerStat, error) { + return GetDockerStatWithContext(context.Background()) +} + +func GetDockerStatWithContext(ctx context.Context) ([]CgroupDockerStat, error) { path, err := exec.LookPath("docker") if err != nil { return nil, ErrDockerNotAvailable @@ -60,6 +65,10 @@ func (c CgroupDockerStat) String() string { // GetDockerIDList returnes a list of DockerID. // This requires certain permission. func GetDockerIDList() ([]string, error) { + return GetDockerIDListWithContext(context.Background()) +} + +func GetDockerIDListWithContext(ctx context.Context) ([]string, error) { path, err := exec.LookPath("docker") if err != nil { return nil, ErrDockerNotAvailable @@ -87,6 +96,10 @@ func GetDockerIDList() ([]string, error) { // If you use container via systemd.slice, you could use // containerID = docker-.scope and base=/sys/fs/cgroup/cpuacct/system.slice/ func CgroupCPU(containerID string, base string) (*cpu.TimesStat, error) { + return CgroupCPUWithContext(context.Background(), containerID, base) +} + +func CgroupCPUWithContext(ctx context.Context, containerID string, base string) (*cpu.TimesStat, error) { statfile := getCgroupFilePath(containerID, base, "cpuacct", "cpuacct.stat") lines, err := common.ReadLines(statfile) if err != nil { @@ -117,10 +130,18 @@ func CgroupCPU(containerID string, base string) (*cpu.TimesStat, error) { } func CgroupCPUDocker(containerid string) (*cpu.TimesStat, error) { + return CgroupCPUDockerWithContext(context.Background(), containerid) +} + +func CgroupCPUDockerWithContext(ctx context.Context, containerid string) (*cpu.TimesStat, error) { return CgroupCPU(containerid, common.HostSys("fs/cgroup/cpuacct/docker")) } func CgroupMem(containerID string, base string) (*CgroupMemStat, error) { + return CgroupMemWithContext(context.Background(), containerID, base) +} + +func CgroupMemWithContext(ctx context.Context, containerID string, base string) (*CgroupMemStat, error) { statfile := getCgroupFilePath(containerID, base, "memory", "memory.stat") // empty containerID means all cgroup @@ -217,6 +238,10 @@ func CgroupMem(containerID string, base string) (*CgroupMemStat, error) { } func CgroupMemDocker(containerID string) (*CgroupMemStat, error) { + return CgroupMemDockerWithContext(context.Background(), containerID) +} + +func CgroupMemDockerWithContext(ctx context.Context, containerID string) (*CgroupMemStat, error) { return CgroupMem(containerID, common.HostSys("fs/cgroup/memory/docker")) } diff --git a/docker/docker_notlinux.go b/docker/docker_notlinux.go index f78fb33..088b3db 100644 --- a/docker/docker_notlinux.go +++ b/docker/docker_notlinux.go @@ -3,6 +3,7 @@ package docker import ( + "context" "encoding/json" "github.com/shirou/gopsutil/cpu" @@ -12,12 +13,20 @@ import ( // GetDockerStat returns a list of Docker basic stats. // This requires certain permission. func GetDockerStat() ([]CgroupDockerStat, error) { + return GetDockerStatWithContext(context.Background()) +} + +func GetDockerStatWithContext(ctx context.Context) ([]CgroupDockerStat, error) { return nil, ErrDockerNotAvailable } // GetDockerIDList returnes a list of DockerID. // This requires certain permission. func GetDockerIDList() ([]string, error) { + return GetDockerIDListWithContext(context.Background()) +} + +func GetDockerIDListWithContext(ctx context.Context) ([]string, error) { return nil, ErrDockerNotAvailable } @@ -26,18 +35,34 @@ func GetDockerIDList() ([]string, error) { // If you use container via systemd.slice, you could use // containerid = docker-.scope and base=/sys/fs/cgroup/cpuacct/system.slice/ func CgroupCPU(containerid string, base string) (*cpu.TimesStat, error) { + return CgroupCPUWithContext(context.Background(), containerid, base) +} + +func CgroupCPUWithContext(ctx context.Context, containerid string, base string) (*cpu.TimesStat, error) { return nil, ErrCgroupNotAvailable } func CgroupCPUDocker(containerid string) (*cpu.TimesStat, error) { + return CgroupCPUDockerWithContext(context.Background(), containerid) +} + +func CgroupCPUDockerWithContext(ctx context.Context, containerid string) (*cpu.TimesStat, error) { return CgroupCPU(containerid, common.HostSys("fs/cgroup/cpuacct/docker")) } func CgroupMem(containerid string, base string) (*CgroupMemStat, error) { + return CgroupMemWithContext(context.Background(), containerid, base) +} + +func CgroupMemWithContext(ctx context.Context, containerid string, base string) (*CgroupMemStat, error) { return nil, ErrCgroupNotAvailable } func CgroupMemDocker(containerid string) (*CgroupMemStat, error) { + return CgroupMemDockerWithContext(context.Background(), containerid) +} + +func CgroupMemDockerWithContext(ctx context.Context, containerid string) (*CgroupMemStat, error) { return CgroupMem(containerid, common.HostSys("fs/cgroup/memory/docker")) } diff --git a/host/host_darwin.go b/host/host_darwin.go index 0ea6d51..c82d990 100644 --- a/host/host_darwin.go +++ b/host/host_darwin.go @@ -4,6 +4,7 @@ package host import ( "bytes" + "context" "encoding/binary" "io/ioutil" "os" @@ -23,6 +24,10 @@ import ( const USER_PROCESS = 7 func Info() (*InfoStat, error) { + return InfoWithContext(context.Background()) +} + +func InfoWithContext(ctx context.Context) (*InfoStat, error) { ret := &InfoStat{ OS: runtime.GOOS, PlatformFamily: "darwin", @@ -77,6 +82,10 @@ func Info() (*InfoStat, error) { var cachedBootTime uint64 func BootTime() (uint64, error) { + return BootTimeWithContext(context.Background()) +} + +func BootTimeWithContext(ctx context.Context) (uint64, error) { t := atomic.LoadUint64(&cachedBootTime) if t != 0 { return t, nil @@ -102,6 +111,10 @@ func uptime(boot uint64) uint64 { } func Uptime() (uint64, error) { + return UptimeWithContext(context.Background()) +} + +func UptimeWithContext(ctx context.Context) (uint64, error) { boot, err := BootTime() if err != nil { return 0, err @@ -110,6 +123,10 @@ func Uptime() (uint64, error) { } func Users() ([]UserStat, error) { + return UsersWithContext(context.Background()) +} + +func UsersWithContext(ctx context.Context) ([]UserStat, error) { utmpfile := "/var/run/utmpx" var ret []UserStat @@ -154,6 +171,10 @@ func Users() ([]UserStat, error) { } func PlatformInformation() (string, string, string, error) { + return PlatformInformationWithContext(context.Background()) +} + +func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) { platform := "" family := "" pver := "" @@ -181,10 +202,18 @@ func PlatformInformation() (string, string, string, error) { } func Virtualization() (string, string, error) { + return VirtualizationWithContext(context.Background()) +} + +func VirtualizationWithContext(ctx context.Context) (string, string, error) { return "", "", common.ErrNotImplementedError } func KernelVersion() (string, error) { + return KernelVersionWithContext(context.Background()) +} + +func KernelVersionWithContext(ctx context.Context) (string, error) { _, _, version, err := PlatformInformation() return version, err } diff --git a/host/host_darwin_cgo.go b/host/host_darwin_cgo.go index be5e18b..f0a4370 100644 --- a/host/host_darwin_cgo.go +++ b/host/host_darwin_cgo.go @@ -6,8 +6,13 @@ package host // #cgo LDFLAGS: -framework IOKit // #include "include/smc.c" import "C" +import "context" func SensorsTemperatures() ([]TemperatureStat, error) { + return SensorsTemperaturesWithContext(context.Background()) +} + +func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) { temperatureKeys := []string{ C.AMBIENT_AIR_0, C.AMBIENT_AIR_1, diff --git a/host/host_darwin_nocgo.go b/host/host_darwin_nocgo.go index 0205888..7869f8c 100644 --- a/host/host_darwin_nocgo.go +++ b/host/host_darwin_nocgo.go @@ -3,8 +3,16 @@ package host -import "github.com/shirou/gopsutil/internal/common" +import ( + "context" + + "github.com/shirou/gopsutil/internal/common" +) func SensorsTemperatures() ([]TemperatureStat, error) { + return SensorsTemperaturesWithContext(context.Background()) +} + +func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) { return []TemperatureStat{}, common.ErrNotImplementedError } diff --git a/host/host_fallback.go b/host/host_fallback.go index 173f58c..f6537a9 100644 --- a/host/host_fallback.go +++ b/host/host_fallback.go @@ -2,28 +2,56 @@ package host -import "github.com/shirou/gopsutil/internal/common" +import ( + "context" + + "github.com/shirou/gopsutil/internal/common" +) func Info() (*InfoStat, error) { + return InfoWithContext(context.Background()) +} + +func InfoWithContext(ctx context.Context) (*InfoStat, error) { return nil, common.ErrNotImplementedError } func BootTime() (uint64, error) { + return BootTimeWithContext(context.Background()) +} + +func BootTimeWithContext(ctx context.Context) (uint64, error) { return 0, common.ErrNotImplementedError } func Uptime() (uint64, error) { + return UptimeWithContext(context.Background()) +} + +func UptimeWithContext(ctx context.Context) (uint64, error) { return 0, common.ErrNotImplementedError } func Users() ([]UserStat, error) { + return UsersWithContext(context.Background()) +} + +func UsersWithContext(ctx context.Context) ([]UserStat, error) { return []UserStat{}, common.ErrNotImplementedError } func Virtualization() (string, string, error) { + return VirtualizationWithContext(context.Background()) +} + +func VirtualizationWithContext(ctx context.Context) (string, string, error) { return "", "", common.ErrNotImplementedError } func KernelVersion() (string, error) { + return KernelVersionWithContext(context.Background()) +} + +func KernelVersionWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } diff --git a/host/host_freebsd.go b/host/host_freebsd.go index d6bcb58..2f51c31 100644 --- a/host/host_freebsd.go +++ b/host/host_freebsd.go @@ -4,6 +4,7 @@ package host import ( "bytes" + "context" "encoding/binary" "io/ioutil" "os" @@ -27,6 +28,10 @@ const ( ) func Info() (*InfoStat, error) { + return InfoWithContext(context.Background()) +} + +func InfoWithContext(ctx context.Context) (*InfoStat, error) { ret := &InfoStat{ OS: runtime.GOOS, PlatformFamily: "freebsd", @@ -74,6 +79,10 @@ func Info() (*InfoStat, error) { var cachedBootTime uint64 func BootTime() (uint64, error) { + return BootTimeWithContext(context.Background()) +} + +func BootTimeWithContext(ctx context.Context) (uint64, error) { t := atomic.LoadUint64(&cachedBootTime) if t != 0 { return t, nil @@ -94,6 +103,10 @@ func uptime(boot uint64) uint64 { } func Uptime() (uint64, error) { + return UptimeWithContext(context.Background()) +} + +func UptimeWithContext(ctx context.Context) (uint64, error) { boot, err := BootTime() if err != nil { return 0, err @@ -102,6 +115,10 @@ func Uptime() (uint64, error) { } func Users() ([]UserStat, error) { + return UsersWithContext(context.Background()) +} + +func UsersWithContext(ctx context.Context) ([]UserStat, error) { utmpfile := "/var/run/utx.active" if !common.PathExists(utmpfile) { utmpfile = "/var/run/utmp" // before 9.0 @@ -147,6 +164,10 @@ func Users() ([]UserStat, error) { } func PlatformInformation() (string, string, string, error) { + return PlatformInformationWithContext(context.Background()) +} + +func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) { platform := "" family := "" version := "" @@ -169,6 +190,10 @@ func PlatformInformation() (string, string, string, error) { } func Virtualization() (string, string, error) { + return VirtualizationWithContext(context.Background()) +} + +func VirtualizationWithContext(ctx context.Context) (string, string, error) { return "", "", common.ErrNotImplementedError } @@ -212,10 +237,18 @@ func getUsersFromUtmp(utmpfile string) ([]UserStat, error) { } func SensorsTemperatures() ([]TemperatureStat, error) { + return SensorsTemperaturesWithContext(context.Background()) +} + +func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) { return []TemperatureStat{}, common.ErrNotImplementedError } func KernelVersion() (string, error) { + return KernelVersionWithContext(context.Background()) +} + +func KernelVersionWithContext(ctx context.Context) (string, error) { _, _, version, err := PlatformInformation() return version, err } diff --git a/host/host_linux.go b/host/host_linux.go index d5ada58..65f3b64 100644 --- a/host/host_linux.go +++ b/host/host_linux.go @@ -4,6 +4,7 @@ package host import ( "bytes" + "context" "encoding/binary" "fmt" "io/ioutil" @@ -31,6 +32,10 @@ type LSB struct { const USER_PROCESS = 7 func Info() (*InfoStat, error) { + return InfoWithContext(context.Background()) +} + +func InfoWithContext(ctx context.Context) (*InfoStat, error) { ret := &InfoStat{ OS: runtime.GOOS, } @@ -91,6 +96,10 @@ var cachedBootTime uint64 // BootTime returns the system boot time expressed in seconds since the epoch. func BootTime() (uint64, error) { + return BootTimeWithContext(context.Background()) +} + +func BootTimeWithContext(ctx context.Context) (uint64, error) { t := atomic.LoadUint64(&cachedBootTime) if t != 0 { return t, nil @@ -124,6 +133,10 @@ func uptime(boot uint64) uint64 { } func Uptime() (uint64, error) { + return UptimeWithContext(context.Background()) +} + +func UptimeWithContext(ctx context.Context) (uint64, error) { boot, err := BootTime() if err != nil { return 0, err @@ -132,6 +145,10 @@ func Uptime() (uint64, error) { } func Users() ([]UserStat, error) { + return UsersWithContext(context.Background()) +} + +func UsersWithContext(ctx context.Context) ([]UserStat, error) { utmpfile := common.HostVar("run/utmp") file, err := os.Open(utmpfile) @@ -249,6 +266,10 @@ func getLSB() (*LSB, error) { } func PlatformInformation() (platform string, family string, version string, err error) { + return PlatformInformationWithContext(context.Background()) +} + +func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) { lsb, err := getLSB() if err != nil { @@ -371,6 +392,10 @@ func PlatformInformation() (platform string, family string, version string, err } func KernelVersion() (version string, err error) { + return KernelVersionWithContext(context.Background()) +} + +func KernelVersionWithContext(ctx context.Context) (version string, err error) { filename := common.HostProc("sys/kernel/osrelease") if common.PathExists(filename) { contents, err := common.ReadLines(filename) @@ -430,6 +455,10 @@ func getSusePlatform(contents []string) string { } func Virtualization() (string, string, error) { + return VirtualizationWithContext(context.Background()) +} + +func VirtualizationWithContext(ctx context.Context) (string, string, error) { var system string var role string @@ -533,6 +562,10 @@ func Virtualization() (string, string, error) { } func SensorsTemperatures() ([]TemperatureStat, error) { + return SensorsTemperaturesWithContext(context.Background()) +} + +func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) { var temperatures []TemperatureStat files, err := filepath.Glob(common.HostSys("/class/hwmon/hwmon*/temp*_*")) if err != nil { diff --git a/host/host_openbsd.go b/host/host_openbsd.go index 13000b5..83c2f7d 100644 --- a/host/host_openbsd.go +++ b/host/host_openbsd.go @@ -4,6 +4,7 @@ package host import ( "bytes" + "context" "encoding/binary" "io/ioutil" "os" @@ -25,6 +26,10 @@ const ( ) func Info() (*InfoStat, error) { + return InfoWithContext(context.Background()) +} + +func InfoWithContext(ctx context.Context) (*InfoStat, error) { ret := &InfoStat{ OS: runtime.GOOS, PlatformFamily: "openbsd", @@ -62,6 +67,10 @@ func Info() (*InfoStat, error) { } func BootTime() (uint64, error) { + return BootTimeWithContext(context.Background()) +} + +func BootTimeWithContext(ctx context.Context) (uint64, error) { val, err := common.DoSysctrl("kern.boottime") if err != nil { return 0, err @@ -80,6 +89,10 @@ func uptime(boot uint64) uint64 { } func Uptime() (uint64, error) { + return UptimeWithContext(context.Background()) +} + +func UptimeWithContext(ctx context.Context) (uint64, error) { boot, err := BootTime() if err != nil { return 0, err @@ -88,6 +101,10 @@ func Uptime() (uint64, error) { } func PlatformInformation() (string, string, string, error) { + return PlatformInformationWithContext(context.Background()) +} + +func PlatformInformationWithContext(ctx context.Context) (string, string, string, error) { platform := "" family := "" version := "" @@ -110,10 +127,18 @@ func PlatformInformation() (string, string, string, error) { } func Virtualization() (string, string, error) { + return VirtualizationWithContext(context.Background()) +} + +func VirtualizationWithContext(ctx context.Context) (string, string, error) { return "", "", common.ErrNotImplementedError } func Users() ([]UserStat, error) { + return UsersWithContext(context.Background()) +} + +func UsersWithContext(ctx context.Context) ([]UserStat, error) { var ret []UserStat utmpfile := "/var/run/utmp" file, err := os.Open(utmpfile) @@ -153,10 +178,18 @@ func Users() ([]UserStat, error) { } func SensorsTemperatures() ([]TemperatureStat, error) { + return SensorsTemperaturesWithContext(context.Background()) +} + +func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) { return []TemperatureStat{}, common.ErrNotImplementedError } func KernelVersion() (string, error) { + return KernelVersionWithContext(context.Background()) +} + +func KernelVersionWithContext(ctx context.Context) (string, error) { _, _, version, err := PlatformInformation() return version, err } diff --git a/host/host_solaris.go b/host/host_solaris.go index 24461fd..2560c06 100644 --- a/host/host_solaris.go +++ b/host/host_solaris.go @@ -3,6 +3,7 @@ package host import ( "bufio" "bytes" + "context" "fmt" "io/ioutil" "os" @@ -17,6 +18,10 @@ import ( ) func Info() (*InfoStat, error) { + return InfoWithContext(context.Background()) +} + +func InfoWithContext(ctx context.Context) (*InfoStat, error) { result := &InfoStat{ OS: runtime.GOOS, } @@ -142,6 +147,10 @@ func Info() (*InfoStat, error) { var kstatMatch = regexp.MustCompile(`([^\s]+)[\s]+([^\s]*)`) func BootTime() (uint64, error) { + return BootTimeWithContext(context.Background()) +} + +func BootTimeWithContext(ctx context.Context) (uint64, error) { kstat, err := exec.LookPath("/usr/bin/kstat") if err != nil { return 0, err @@ -161,6 +170,10 @@ func BootTime() (uint64, error) { } func Uptime() (uint64, error) { + return UptimeWithContext(context.Background()) +} + +func UptimeWithContext(ctx context.Context) (uint64, error) { bootTime, err := BootTime() if err != nil { return 0, err @@ -173,18 +186,34 @@ func uptimeSince(since uint64) uint64 { } func Users() ([]UserStat, error) { + return UsersWithContext(context.Background()) +} + +func UsersWithContext(ctx context.Context) ([]UserStat, error) { return []UserStat{}, common.ErrNotImplementedError } func SensorsTemperatures() ([]TemperatureStat, error) { + return SensorsTemperaturesWithContext(context.Background()) +} + +func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) { return []TemperatureStat{}, common.ErrNotImplementedError } func Virtualization() (string, string, error) { + return VirtualizationWithContext(context.Background()) +} + +func VirtualizationWithContext(ctx context.Context) (string, string, error) { return "", "", common.ErrNotImplementedError } func KernelVersion() (string, error) { + return KernelVersionWithContext(context.Background()) +} + +func KernelVersionWithContext(ctx context.Context) (string, error) { // Parse versions from output of `uname(1)` uname, err := exec.LookPath("/usr/bin/uname") if err != nil { diff --git a/host/host_windows.go b/host/host_windows.go index 920cec9..643bd66 100644 --- a/host/host_windows.go +++ b/host/host_windows.go @@ -32,6 +32,10 @@ type Win32_OperatingSystem struct { } func Info() (*InfoStat, error) { + return InfoWithContext(context.Background()) +} + +func InfoWithContext(ctx context.Context) (*InfoStat, error) { ret := &InfoStat{ OS: runtime.GOOS, } @@ -108,6 +112,10 @@ func getMachineGuid() (string, error) { } func GetOSInfo() (Win32_OperatingSystem, error) { + return GetOSInfoWithContext(context.Background()) +} + +func GetOSInfoWithContext(ctx context.Context) (Win32_OperatingSystem, error) { var dst []Win32_OperatingSystem q := wmi.CreateQuery(&dst, "") ctx, cancel := context.WithTimeout(context.Background(), common.Timeout) @@ -123,6 +131,10 @@ func GetOSInfo() (Win32_OperatingSystem, error) { } func Uptime() (uint64, error) { + return UptimeWithContext(context.Background()) +} + +func UptimeWithContext(ctx context.Context) (uint64, error) { if osInfo == nil { _, err := GetOSInfo() if err != nil { @@ -142,6 +154,10 @@ func bootTime(up uint64) uint64 { var cachedBootTime uint64 func BootTime() (uint64, error) { + return BootTimeWithContext(context.Background()) +} + +func BootTimeWithContext(ctx context.Context) (uint64, error) { t := atomic.LoadUint64(&cachedBootTime) if t != 0 { return t, nil @@ -156,6 +172,10 @@ func BootTime() (uint64, error) { } func PlatformInformation() (platform string, family string, version string, err error) { + return PlatformInformationWithContext(context.Background()) +} + +func PlatformInformationWithContext(ctx context.Context) (platform string, family string, version string, err error) { if osInfo == nil { _, err = GetOSInfo() if err != nil { @@ -183,20 +203,36 @@ func PlatformInformation() (platform string, family string, version string, err } func Users() ([]UserStat, error) { + return UsersWithContext(context.Background()) +} + +func UsersWithContext(ctx context.Context) ([]UserStat, error) { var ret []UserStat return ret, nil } func SensorsTemperatures() ([]TemperatureStat, error) { + return SensorsTemperaturesWithContext(context.Background()) +} + +func SensorsTemperaturesWithContext(ctx context.Context) ([]TemperatureStat, error) { return []TemperatureStat{}, common.ErrNotImplementedError } func Virtualization() (string, string, error) { + return VirtualizationWithContext(context.Background()) +} + +func VirtualizationWithContext(ctx context.Context) (string, string, error) { return "", "", common.ErrNotImplementedError } func KernelVersion() (string, error) { + return KernelVersionWithContext(context.Background()) +} + +func KernelVersionWithContext(ctx context.Context) (string, error) { _, _, version, err := PlatformInformation() return version, err } diff --git a/load/load_bsd.go b/load/load_bsd.go index 4fda3c0..cf524ef 100644 --- a/load/load_bsd.go +++ b/load/load_bsd.go @@ -3,6 +3,7 @@ package load import ( + "context" "os/exec" "strings" "unsafe" @@ -11,6 +12,10 @@ import ( ) func Avg() (*AvgStat, error) { + return AvgWithContext(context.Background()) +} + +func AvgWithContext(ctx context.Context) (*AvgStat, error) { // This SysctlRaw method borrowed from // https://github.com/prometheus/node_exporter/blob/master/collector/loadavg_freebsd.go type loadavg struct { @@ -36,6 +41,10 @@ func Avg() (*AvgStat, error) { // darwin use ps command to get process running/blocked count. // Almost same as Darwin implementation, but state is different. func Misc() (*MiscStat, error) { + return MiscWithContext(context.Background()) +} + +func MiscWithContext(ctx context.Context) (*MiscStat, error) { bin, err := exec.LookPath("ps") if err != nil { return nil, err diff --git a/load/load_darwin.go b/load/load_darwin.go index 34e0653..50f626c 100644 --- a/load/load_darwin.go +++ b/load/load_darwin.go @@ -3,6 +3,7 @@ package load import ( + "context" "os/exec" "strconv" "strings" @@ -11,6 +12,10 @@ import ( ) func Avg() (*AvgStat, error) { + return AvgWithContext(context.Background()) +} + +func AvgWithContext(ctx context.Context) (*AvgStat, error) { values, err := common.DoSysctrl("vm.loadavg") if err != nil { return nil, err @@ -43,6 +48,10 @@ func Avg() (*AvgStat, error) { // Almost same as FreeBSD implementation, but state is different. // U means 'Uninterruptible Sleep'. func Misc() (*MiscStat, error) { + return MiscWithContext(context.Background()) +} + +func MiscWithContext(ctx context.Context) (*MiscStat, error) { bin, err := exec.LookPath("ps") if err != nil { return nil, err diff --git a/load/load_fallback.go b/load/load_fallback.go index a896d61..1e3ade0 100644 --- a/load/load_fallback.go +++ b/load/load_fallback.go @@ -2,12 +2,24 @@ package load -import "github.com/shirou/gopsutil/internal/common" +import ( + "context" + + "github.com/shirou/gopsutil/internal/common" +) func Avg() (*AvgStat, error) { + return AvgWithContext(context.Background()) +} + +func AvgWithContext(ctx context.Context) (*AvgStat, error) { return nil, common.ErrNotImplementedError } func Misc() (*MiscStat, error) { + return MiscWithContext(context.Background()) +} + +func MiscWithContext(ctx context.Context) (*MiscStat, error) { return nil, common.ErrNotImplementedError } diff --git a/load/load_linux.go b/load/load_linux.go index c455397..63c26a2 100644 --- a/load/load_linux.go +++ b/load/load_linux.go @@ -3,6 +3,7 @@ package load import ( + "context" "io/ioutil" "strconv" "strings" @@ -11,6 +12,10 @@ import ( ) func Avg() (*AvgStat, error) { + return AvgWithContext(context.Background()) +} + +func AvgWithContext(ctx context.Context) (*AvgStat, error) { filename := common.HostProc("loadavg") line, err := ioutil.ReadFile(filename) if err != nil { @@ -44,6 +49,10 @@ func Avg() (*AvgStat, error) { // Misc returnes miscellaneous host-wide statistics. // Note: the name should be changed near future. func Misc() (*MiscStat, error) { + return MiscWithContext(context.Background()) +} + +func MiscWithContext(ctx context.Context) (*MiscStat, error) { filename := common.HostProc("stat") out, err := ioutil.ReadFile(filename) if err != nil { diff --git a/load/load_windows.go b/load/load_windows.go index c45c154..42968b3 100644 --- a/load/load_windows.go +++ b/load/load_windows.go @@ -3,16 +3,26 @@ package load import ( + "context" + "github.com/shirou/gopsutil/internal/common" ) func Avg() (*AvgStat, error) { + return AvgWithContext(context.Background()) +} + +func AvgWithContext(ctx context.Context) (*AvgStat, error) { ret := AvgStat{} return &ret, common.ErrNotImplementedError } func Misc() (*MiscStat, error) { + return MiscWithContext(context.Background()) +} + +func MiscWithContext(ctx context.Context) (*MiscStat, error) { ret := MiscStat{} return &ret, common.ErrNotImplementedError diff --git a/mem/mem_darwin.go b/mem/mem_darwin.go index fde000e..3e259a0 100644 --- a/mem/mem_darwin.go +++ b/mem/mem_darwin.go @@ -3,6 +3,7 @@ package mem import ( + "context" "encoding/binary" "strconv" "strings" @@ -28,6 +29,10 @@ func getHwMemsize() (uint64, error) { // SwapMemory returns swapinfo. func SwapMemory() (*SwapMemoryStat, error) { + return SwapMemoryWithContext(context.Background()) +} + +func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) { var ret *SwapMemoryStat swapUsage, err := common.DoSysctrl("vm.swapusage") diff --git a/mem/mem_darwin_cgo.go b/mem/mem_darwin_cgo.go index 4b5a6b9..389f8cd 100644 --- a/mem/mem_darwin_cgo.go +++ b/mem/mem_darwin_cgo.go @@ -9,6 +9,7 @@ package mem import "C" import ( + "context" "fmt" "unsafe" @@ -17,6 +18,10 @@ import ( // VirtualMemory returns VirtualmemoryStat. func VirtualMemory() (*VirtualMemoryStat, error) { + return VirtualMemoryWithContext(context.Background()) +} + +func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) { count := C.mach_msg_type_number_t(C.HOST_VM_INFO_COUNT) var vmstat C.vm_statistics_data_t diff --git a/mem/mem_darwin_nocgo.go b/mem/mem_darwin_nocgo.go index 79af790..dd7c2e6 100644 --- a/mem/mem_darwin_nocgo.go +++ b/mem/mem_darwin_nocgo.go @@ -4,6 +4,7 @@ package mem import ( + "context" "os/exec" "strconv" "strings" @@ -68,6 +69,10 @@ func parseVMStat(out string, vms *VirtualMemoryStat) error { // VirtualMemory returns VirtualmemoryStat. func VirtualMemory() (*VirtualMemoryStat, error) { + return VirtualMemoryWithContext(context.Background()) +} + +func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) { ret := &VirtualMemoryStat{} total, err := getHwMemsize() diff --git a/mem/mem_fallback.go b/mem/mem_fallback.go index e61fe4b..2a0fd45 100644 --- a/mem/mem_fallback.go +++ b/mem/mem_fallback.go @@ -2,12 +2,24 @@ package mem -import "github.com/shirou/gopsutil/internal/common" +import ( + "context" + + "github.com/shirou/gopsutil/internal/common" +) func VirtualMemory() (*VirtualMemoryStat, error) { + return VirtualMemoryWithContext(context.Background()) +} + +func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) { return nil, common.ErrNotImplementedError } func SwapMemory() (*SwapMemoryStat, error) { + return SwapMemoryWithContext(context.Background()) +} + +func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) { return nil, common.ErrNotImplementedError } diff --git a/mem/mem_freebsd.go b/mem/mem_freebsd.go index 55e78d6..e691227 100644 --- a/mem/mem_freebsd.go +++ b/mem/mem_freebsd.go @@ -3,6 +3,7 @@ package mem import ( + "context" "errors" "os/exec" "strconv" @@ -12,6 +13,10 @@ import ( ) func VirtualMemory() (*VirtualMemoryStat, error) { + return VirtualMemoryWithContext(context.Background()) +} + +func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) { pageSize, err := unix.SysctlUint32("vm.stats.vm.v_page_size") if err != nil { return nil, err @@ -66,6 +71,10 @@ func VirtualMemory() (*VirtualMemoryStat, error) { // Return swapinfo // FreeBSD can have multiple swap devices. but use only first device func SwapMemory() (*SwapMemoryStat, error) { + return SwapMemoryWithContext(context.Background()) +} + +func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) { swapinfo, err := exec.LookPath("swapinfo") if err != nil { return nil, err diff --git a/mem/mem_linux.go b/mem/mem_linux.go index fda3345..fe6c4e1 100644 --- a/mem/mem_linux.go +++ b/mem/mem_linux.go @@ -3,6 +3,7 @@ package mem import ( + "context" "strconv" "strings" @@ -11,6 +12,10 @@ import ( ) func VirtualMemory() (*VirtualMemoryStat, error) { + return VirtualMemoryWithContext(context.Background()) +} + +func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) { filename := common.HostProc("meminfo") lines, _ := common.ReadLines(filename) // flag if MemAvailable is in /proc/meminfo (kernel 3.14+) @@ -72,6 +77,10 @@ func VirtualMemory() (*VirtualMemoryStat, error) { } func SwapMemory() (*SwapMemoryStat, error) { + return SwapMemoryWithContext(context.Background()) +} + +func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) { sysinfo := &unix.Sysinfo_t{} if err := unix.Sysinfo(sysinfo); err != nil { diff --git a/mem/mem_openbsd.go b/mem/mem_openbsd.go index 2e94bea..e4834f3 100644 --- a/mem/mem_openbsd.go +++ b/mem/mem_openbsd.go @@ -4,14 +4,20 @@ package mem import ( "bytes" + "context" "encoding/binary" "errors" "fmt" - "github.com/shirou/gopsutil/internal/common" "os/exec" + + "github.com/shirou/gopsutil/internal/common" ) func GetPageSize() (uint64, error) { + return GetPageSizeWithContext(context.Background()) +} + +func GetPageSizeWithContext(ctx context.Context) (uint64, error) { mib := []int32{CTLVm, VmUvmexp} buf, length, err := common.CallSyscall(mib) if err != nil { @@ -30,6 +36,10 @@ func GetPageSize() (uint64, error) { } func VirtualMemory() (*VirtualMemoryStat, error) { + return VirtualMemoryWithContext(context.Background()) +} + +func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) { mib := []int32{CTLVm, VmUvmexp} buf, length, err := common.CallSyscall(mib) if err != nil { @@ -80,6 +90,10 @@ func VirtualMemory() (*VirtualMemoryStat, error) { // Return swapctl summary info func SwapMemory() (*SwapMemoryStat, error) { + return SwapMemoryWithContext(context.Background()) +} + +func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) { swapctl, err := exec.LookPath("swapctl") if err != nil { return nil, err diff --git a/mem/mem_solaris.go b/mem/mem_solaris.go index aa4f253..d6c6a5f 100644 --- a/mem/mem_solaris.go +++ b/mem/mem_solaris.go @@ -1,6 +1,7 @@ package mem import ( + "context" "errors" "fmt" "os/exec" @@ -14,6 +15,10 @@ import ( // VirtualMemory for Solaris is a minimal implementation which only returns // what Nomad needs. It does take into account global vs zone, however. func VirtualMemory() (*VirtualMemoryStat, error) { + return VirtualMemoryWithContext(context.Background()) +} + +func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) { result := &VirtualMemoryStat{} zoneName, err := zoneName() @@ -39,6 +44,10 @@ func VirtualMemory() (*VirtualMemoryStat, error) { } func SwapMemory() (*SwapMemoryStat, error) { + return SwapMemoryWithContext(context.Background()) +} + +func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) { return nil, common.ErrNotImplementedError } diff --git a/mem/mem_windows.go b/mem/mem_windows.go index 806cedb..d40f6cf 100644 --- a/mem/mem_windows.go +++ b/mem/mem_windows.go @@ -3,6 +3,7 @@ package mem import ( + "context" "unsafe" "github.com/shirou/gopsutil/internal/common" @@ -11,7 +12,7 @@ import ( var ( procGlobalMemoryStatusEx = common.Modkernel32.NewProc("GlobalMemoryStatusEx") - procGetPerformanceInfo = common.ModPsapi.NewProc("GetPerformanceInfo") + procGetPerformanceInfo = common.ModPsapi.NewProc("GetPerformanceInfo") ) type memoryStatusEx struct { @@ -27,6 +28,10 @@ type memoryStatusEx struct { } func VirtualMemory() (*VirtualMemoryStat, error) { + return VirtualMemoryWithContext(context.Background()) +} + +func VirtualMemoryWithContext(ctx context.Context) (*VirtualMemoryStat, error) { var memInfo memoryStatusEx memInfo.cbSize = uint32(unsafe.Sizeof(memInfo)) mem, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&memInfo))) @@ -45,23 +50,27 @@ func VirtualMemory() (*VirtualMemoryStat, error) { } type performanceInformation struct { - cb uint32 - commitTotal uint64 - commitLimit uint64 - commitPeak uint64 - physicalTotal uint64 + cb uint32 + commitTotal uint64 + commitLimit uint64 + commitPeak uint64 + physicalTotal uint64 physicalAvailable uint64 - systemCache uint64 - kernelTotal uint64 - kernelPaged uint64 - kernelNonpaged uint64 - pageSize uint64 - handleCount uint32 - processCount uint32 - threadCount uint32 + systemCache uint64 + kernelTotal uint64 + kernelPaged uint64 + kernelNonpaged uint64 + pageSize uint64 + handleCount uint32 + processCount uint32 + threadCount uint32 } func SwapMemory() (*SwapMemoryStat, error) { + return SwapMemoryWithContext(context.Background()) +} + +func SwapMemoryWithContext(ctx context.Context) (*SwapMemoryStat, error) { var perfInfo performanceInformation perfInfo.cb = uint32(unsafe.Sizeof(perfInfo)) mem, _, _ := procGetPerformanceInfo.Call(uintptr(unsafe.Pointer(&perfInfo)), uintptr(perfInfo.cb)) @@ -72,12 +81,11 @@ func SwapMemory() (*SwapMemoryStat, error) { used := perfInfo.commitTotal * perfInfo.pageSize free := tot - used ret := &SwapMemoryStat{ - Total: tot, - Used: used, - Free: free, - UsedPercent: float64(used/tot), + Total: tot, + Used: used, + Free: free, + UsedPercent: float64(used / tot), } return ret, nil } - diff --git a/net/net.go b/net/net.go index 48660ec..428e68e 100644 --- a/net/net.go +++ b/net/net.go @@ -1,6 +1,7 @@ package net import ( + "context" "encoding/json" "fmt" "net" @@ -111,6 +112,10 @@ func (n InterfaceAddr) String() string { } func Interfaces() ([]InterfaceStat, error) { + return InterfacesWithContext(context.Background()) +} + +func InterfacesWithContext(ctx context.Context) ([]InterfaceStat, error) { is, err := net.Interfaces() if err != nil { return nil, err diff --git a/net/net_darwin.go b/net/net_darwin.go index c60a004..2afb0f0 100644 --- a/net/net_darwin.go +++ b/net/net_darwin.go @@ -3,6 +3,7 @@ package net import ( + "context" "errors" "fmt" "os/exec" @@ -164,6 +165,10 @@ func (min mapInterfaceNameUsage) notTruncated() []string { // lo0 16384 ::1/128 ::1 869107 - 169411755 869107 - 169411755 - - // lo0 16384 127 127.0.0.1 869107 - 169411755 869107 - 169411755 - - func IOCounters(pernic bool) ([]IOCountersStat, error) { + return IOCountersWithContext(context.Background(), pernic) +} + +func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) { var ( ret []IOCountersStat retIndex int @@ -251,10 +256,18 @@ func IOCounters(pernic bool) ([]IOCountersStat, error) { // NetIOCountersByFile is an method which is added just a compatibility for linux. func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) { + return IOCountersByFileWithContext(context.Background(), pernic, filename) +} + +func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) { return IOCounters(pernic) } func FilterCounters() ([]FilterStat, error) { + return FilterCountersWithContext(context.Background()) +} + +func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) { return nil, errors.New("NetFilterCounters not implemented for darwin") } @@ -263,5 +276,9 @@ func FilterCounters() ([]FilterStat, error) { // just the protocols in the list are returned. // Not Implemented for Darwin func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) { + return ProtoCountersWithContext(context.Background(), protocols) +} + +func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) { return nil, errors.New("NetProtoCounters not implemented for darwin") } diff --git a/net/net_fallback.go b/net/net_fallback.go index 653bd47..7c5e632 100644 --- a/net/net_fallback.go +++ b/net/net_fallback.go @@ -2,24 +2,48 @@ package net -import "github.com/shirou/gopsutil/internal/common" +import ( + "context" + + "github.com/shirou/gopsutil/internal/common" +) func IOCounters(pernic bool) ([]IOCountersStat, error) { + return IOCountersWithContext(context.Background(), pernic) +} + +func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) { return []IOCountersStat{}, common.ErrNotImplementedError } func FilterCounters() ([]FilterStat, error) { + return FilterCountersWithContext(context.Background()) +} + +func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) { return []FilterStat{}, common.ErrNotImplementedError } func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) { + return ProtoCountersWithContext(context.Background(), protocols) +} + +func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) { return []ProtoCountersStat{}, common.ErrNotImplementedError } func Connections(kind string) ([]ConnectionStat, error) { + return ConnectionsWithContext(context.Background(), kind) +} + +func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) { return []ConnectionStat{}, common.ErrNotImplementedError } func ConnectionsMax(kind string, max int) ([]ConnectionStat, error) { + return ConnectionsMaxWithContext(context.Background(), kind, max) +} + +func ConnectionsMaxWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) { return []ConnectionStat{}, common.ErrNotImplementedError } diff --git a/net/net_freebsd.go b/net/net_freebsd.go index 2b54655..9daed8d 100644 --- a/net/net_freebsd.go +++ b/net/net_freebsd.go @@ -3,6 +3,7 @@ package net import ( + "context" "errors" "os/exec" "strconv" @@ -12,6 +13,10 @@ import ( ) func IOCounters(pernic bool) ([]IOCountersStat, error) { + return IOCountersWithContext(context.Background(), pernic) +} + +func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) { netstat, err := exec.LookPath("/usr/bin/netstat") if err != nil { return nil, err @@ -92,10 +97,18 @@ func IOCounters(pernic bool) ([]IOCountersStat, error) { // NetIOCountersByFile is an method which is added just a compatibility for linux. func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) { + return IOCountersByFileWithContext(context.Background(), pernic, filename) +} + +func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) { return IOCounters(pernic) } func FilterCounters() ([]FilterStat, error) { + return FilterCountersWithContext(context.Background()) +} + +func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) { return nil, errors.New("NetFilterCounters not implemented for freebsd") } @@ -104,5 +117,9 @@ func FilterCounters() ([]FilterStat, error) { // just the protocols in the list are returned. // Not Implemented for FreeBSD func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) { + return ProtoCountersWithContext(context.Background(), protocols) +} + +func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) { return nil, errors.New("NetProtoCounters not implemented for freebsd") } diff --git a/net/net_linux.go b/net/net_linux.go index 6d798fc..fc2b22e 100644 --- a/net/net_linux.go +++ b/net/net_linux.go @@ -4,6 +4,7 @@ package net import ( "bytes" + "context" "encoding/hex" "errors" "fmt" @@ -23,11 +24,19 @@ import ( // every network interface installed on the system is returned // separately. func IOCounters(pernic bool) ([]IOCountersStat, error) { + return IOCountersWithContext(context.Background(), pernic) +} + +func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) { filename := common.HostProc("net/dev") return IOCountersByFile(pernic, filename) } func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) { + return IOCountersByFileWithContext(context.Background(), pernic, filename) +} + +func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) { lines, err := common.ReadLines(filename) if err != nil { return nil, err @@ -132,6 +141,10 @@ var netProtocols = []string{ // Available protocols: // ip,icmp,icmpmsg,tcp,udp,udplite func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) { + return ProtoCountersWithContext(context.Background(), protocols) +} + +func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) { if len(protocols) == 0 { protocols = netProtocols } @@ -191,6 +204,10 @@ func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) { // the currently in use conntrack count and the max. // If the file does not exist or is invalid it will return nil. func FilterCounters() ([]FilterStat, error) { + return FilterCountersWithContext(context.Background()) +} + +func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) { countfile := common.HostProc("sys/net/netfilter/nf_conntrack_count") maxfile := common.HostProc("sys/net/netfilter/nf_conntrack_max") @@ -294,17 +311,29 @@ type connTmp struct { // Return a list of network connections opened. func Connections(kind string) ([]ConnectionStat, error) { + return ConnectionsWithContext(context.Background(), kind) +} + +func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) { return ConnectionsPid(kind, 0) } // Return a list of network connections opened returning at most `max` // connections for each running process. func ConnectionsMax(kind string, max int) ([]ConnectionStat, error) { + return ConnectionsMaxWithContext(context.Background(), kind, max) +} + +func ConnectionsMaxWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) { return ConnectionsPidMax(kind, 0, max) } // Return a list of network connections opened by a process. func ConnectionsPid(kind string, pid int32) ([]ConnectionStat, error) { + return ConnectionsPidWithContext(context.Background(), kind, pid) +} + +func ConnectionsPidWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) { tmap, ok := netConnectionKindMap[kind] if !ok { return nil, fmt.Errorf("invalid kind, %s", kind) @@ -329,6 +358,10 @@ func ConnectionsPid(kind string, pid int32) ([]ConnectionStat, error) { // Return up to `max` network connections opened by a process. func ConnectionsPidMax(kind string, pid int32, max int) ([]ConnectionStat, error) { + return ConnectionsPidMaxWithContext(context.Background(), kind, pid, max) +} + +func ConnectionsPidMaxWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) { tmap, ok := netConnectionKindMap[kind] if !ok { return nil, fmt.Errorf("invalid kind, %s", kind) @@ -459,6 +492,10 @@ func getProcInodes(root string, pid int32, max int) (map[string][]inodeMap, erro // FIXME: Import process occures import cycle. // move to common made other platform breaking. Need consider. func Pids() ([]int32, error) { + return PidsWithContext(context.Background()) +} + +func PidsWithContext(ctx context.Context) ([]int32, error) { var ret []int32 d, err := os.Open(common.HostProc()) @@ -592,6 +629,10 @@ func decodeAddress(family uint32, src string) (Addr, error) { // Reverse reverses array of bytes. func Reverse(s []byte) []byte { + return ReverseWithContext(context.Background(), s) +} + +func ReverseWithContext(ctx context.Context, s []byte) []byte { for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 { s[i], s[j] = s[j], s[i] } diff --git a/net/net_openbsd.go b/net/net_openbsd.go index 63caff5..4b194eb 100644 --- a/net/net_openbsd.go +++ b/net/net_openbsd.go @@ -3,6 +3,7 @@ package net import ( + "context" "errors" "fmt" "os/exec" @@ -97,6 +98,10 @@ func ParseNetstat(output string, mode string, } func IOCounters(pernic bool) ([]IOCountersStat, error) { + return IOCountersWithContext(context.Background(), pernic) +} + +func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) { netstat, err := exec.LookPath("netstat") if err != nil { return nil, err @@ -136,10 +141,18 @@ func IOCounters(pernic bool) ([]IOCountersStat, error) { // NetIOCountersByFile is an method which is added just a compatibility for linux. func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) { + return IOCountersByFileWithContext(context.Background(), pernic, filename) +} + +func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) { return IOCounters(pernic) } func FilterCounters() ([]FilterStat, error) { + return FilterCountersWithContext(context.Background()) +} + +func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) { return nil, errors.New("NetFilterCounters not implemented for openbsd") } @@ -148,6 +161,10 @@ func FilterCounters() ([]FilterStat, error) { // just the protocols in the list are returned. // Not Implemented for OpenBSD func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) { + return ProtoCountersWithContext(context.Background(), protocols) +} + +func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) { return nil, errors.New("NetProtoCounters not implemented for openbsd") } @@ -233,6 +250,10 @@ func parseNetstatAddr(local string, remote string, family uint32) (laddr Addr, r // Return a list of network connections opened. func Connections(kind string) ([]ConnectionStat, error) { + return ConnectionsWithContext(context.Background(), kind) +} + +func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) { var ret []ConnectionStat args := []string{"-na"} diff --git a/net/net_unix.go b/net/net_unix.go index 1224128..5ceb9cc 100644 --- a/net/net_unix.go +++ b/net/net_unix.go @@ -3,6 +3,7 @@ package net import ( + "context" "strings" "github.com/shirou/gopsutil/internal/common" @@ -10,17 +11,29 @@ import ( // Return a list of network connections opened. func Connections(kind string) ([]ConnectionStat, error) { + return ConnectionsWithContext(context.Background(), kind) +} + +func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) { return ConnectionsPid(kind, 0) } // Return a list of network connections opened returning at most `max` // connections for each running process. func ConnectionsMax(kind string, max int) ([]ConnectionStat, error) { + return ConnectionsMaxWithContext(context.Background(), kind, max) +} + +func ConnectionsMaxWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) { return []ConnectionStat{}, common.ErrNotImplementedError } // Return a list of network connections opened by a process. func ConnectionsPid(kind string, pid int32) ([]ConnectionStat, error) { + return ConnectionsPidWithContext(context.Background(), kind, pid) +} + +func ConnectionsPidWithContext(ctx context.Context, kind string, pid int32) ([]ConnectionStat, error) { var ret []ConnectionStat args := []string{"-i"} @@ -75,5 +88,9 @@ func ConnectionsPid(kind string, pid int32) ([]ConnectionStat, error) { // Return up to `max` network connections opened by a process. func ConnectionsPidMax(kind string, pid int32, max int) ([]ConnectionStat, error) { + return ConnectionsPidMaxWithContext(context.Background(), kind, pid, max) +} + +func ConnectionsPidMaxWithContext(ctx context.Context, kind string, pid int32, max int) ([]ConnectionStat, error) { return []ConnectionStat{}, common.ErrNotImplementedError } diff --git a/net/net_windows.go b/net/net_windows.go index e26a130..7fff20e 100644 --- a/net/net_windows.go +++ b/net/net_windows.go @@ -3,6 +3,7 @@ package net import ( + "context" "errors" "net" "os" @@ -30,6 +31,10 @@ const ( ) func IOCounters(pernic bool) ([]IOCountersStat, error) { + return IOCountersWithContext(context.Background(), pernic) +} + +func IOCountersWithContext(ctx context.Context, pernic bool) ([]IOCountersStat, error) { ifs, err := net.Interfaces() if err != nil { return nil, err @@ -66,11 +71,19 @@ func IOCounters(pernic bool) ([]IOCountersStat, error) { // NetIOCountersByFile is an method which is added just a compatibility for linux. func IOCountersByFile(pernic bool, filename string) ([]IOCountersStat, error) { + return IOCountersByFileWithContext(context.Background(), pernic, filename) +} + +func IOCountersByFileWithContext(ctx context.Context, pernic bool, filename string) ([]IOCountersStat, error) { return IOCounters(pernic) } // Return a list of network connections opened by a process func Connections(kind string) ([]ConnectionStat, error) { + return ConnectionsWithContext(context.Background(), kind) +} + +func ConnectionsWithContext(ctx context.Context, kind string) ([]ConnectionStat, error) { var ret []ConnectionStat return ret, common.ErrNotImplementedError @@ -79,10 +92,18 @@ func Connections(kind string) ([]ConnectionStat, error) { // Return a list of network connections opened returning at most `max` // connections for each running process. func ConnectionsMax(kind string, max int) ([]ConnectionStat, error) { + return ConnectionsMaxWithContext(context.Background(), kind, max) +} + +func ConnectionsMaxWithContext(ctx context.Context, kind string, max int) ([]ConnectionStat, error) { return []ConnectionStat{}, common.ErrNotImplementedError } func FilterCounters() ([]FilterStat, error) { + return FilterCountersWithContext(context.Background()) +} + +func FilterCountersWithContext(ctx context.Context) ([]FilterStat, error) { return nil, errors.New("NetFilterCounters not implemented for windows") } @@ -91,5 +112,9 @@ func FilterCounters() ([]FilterStat, error) { // just the protocols in the list are returned. // Not Implemented for Windows func ProtoCounters(protocols []string) ([]ProtoCountersStat, error) { + return ProtoCountersWithContext(context.Background(), protocols) +} + +func ProtoCountersWithContext(ctx context.Context, protocols []string) ([]ProtoCountersStat, error) { return nil, errors.New("NetProtoCounters not implemented for windows") } diff --git a/process/process.go b/process/process.go index df5da2e..09b1e6a 100644 --- a/process/process.go +++ b/process/process.go @@ -1,6 +1,7 @@ package process import ( + "context" "encoding/json" "runtime" "time" @@ -125,6 +126,10 @@ func (p NumCtxSwitchesStat) String() string { } func PidExists(pid int32) (bool, error) { + return PidExistsWithContext(context.Background(), pid) +} + +func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) { pids, err := Pids() if err != nil { return false, err @@ -142,6 +147,10 @@ func PidExists(pid int32) (bool, error) { // If interval is 0, return difference from last call(non-blocking). // If interval > 0, wait interval sec and return diffrence between start and end. func (p *Process) Percent(interval time.Duration) (float64, error) { + return p.PercentWithContext(context.Background(), interval) +} + +func (p *Process) PercentWithContext(ctx context.Context, interval time.Duration) (float64, error) { cpuTimes, err := p.Times() if err != nil { return 0, err @@ -185,6 +194,10 @@ func calculatePercent(t1, t2 *cpu.TimesStat, delta float64, numcpu int) float64 // MemoryPercent returns how many percent of the total RAM this process uses func (p *Process) MemoryPercent() (float32, error) { + return p.MemoryPercentWithContext(context.Background()) +} + +func (p *Process) MemoryPercentWithContext(ctx context.Context) (float32, error) { machineMemory, err := mem.VirtualMemory() if err != nil { return 0, err @@ -202,6 +215,10 @@ func (p *Process) MemoryPercent() (float32, error) { // CPU_Percent returns how many percent of the CPU time this process uses func (p *Process) CPUPercent() (float64, error) { + return p.CPUPercentWithContext(context.Background()) +} + +func (p *Process) CPUPercentWithContext(ctx context.Context) (float64, error) { crt_time, err := p.CreateTime() if err != nil { return 0, err diff --git a/process/process_darwin.go b/process/process_darwin.go index cc289d2..005ae3c 100644 --- a/process/process_darwin.go +++ b/process/process_darwin.go @@ -4,6 +4,7 @@ package process import ( "bytes" + "context" "encoding/binary" "fmt" "os/exec" @@ -44,6 +45,10 @@ type MemoryMapsStat struct { } func Pids() ([]int32, error) { + return PidsWithContext(context.Background()) +} + +func PidsWithContext(ctx context.Context) ([]int32, error) { var ret []int32 pids, err := callPs("pid", 0, false) @@ -63,6 +68,10 @@ func Pids() ([]int32, error) { } func (p *Process) Ppid() (int32, error) { + return p.PpidWithContext(context.Background()) +} + +func (p *Process) PpidWithContext(ctx context.Context) (int32, error) { r, err := callPs("ppid", p.Pid, false) if err != nil { return 0, err @@ -76,6 +85,10 @@ func (p *Process) Ppid() (int32, error) { return int32(v), err } func (p *Process) Name() (string, error) { + return p.NameWithContext(context.Background()) +} + +func (p *Process) NameWithContext(ctx context.Context) (string, error) { k, err := p.getKProc() if err != nil { return "", err @@ -84,6 +97,10 @@ func (p *Process) Name() (string, error) { return common.IntToString(k.Proc.P_comm[:]), nil } func (p *Process) Exe() (string, error) { + return p.ExeWithContext(context.Background()) +} + +func (p *Process) ExeWithContext(ctx context.Context) (string, error) { lsof_bin, err := exec.LookPath("lsof") if err != nil { return "", err @@ -117,6 +134,10 @@ func (p *Process) Exe() (string, error) { // Cmdline returns the command line arguments of the process as a string with // each argument separated by 0x20 ascii character. func (p *Process) Cmdline() (string, error) { + return p.CmdlineWithContext(context.Background()) +} + +func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) { r, err := callPs("command", p.Pid, false) if err != nil { return "", err @@ -130,6 +151,10 @@ func (p *Process) Cmdline() (string, error) { // reported as two separate items. In order to do something better CGO would be needed // to use the native darwin functions. func (p *Process) CmdlineSlice() ([]string, error) { + return p.CmdlineSliceWithContext(context.Background()) +} + +func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) { r, err := callPs("command", p.Pid, false) if err != nil { return nil, err @@ -137,6 +162,10 @@ func (p *Process) CmdlineSlice() ([]string, error) { return r[0], err } func (p *Process) CreateTime() (int64, error) { + return p.CreateTimeWithContext(context.Background()) +} + +func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) { r, err := callPs("etime", p.Pid, false) if err != nil { return 0, err @@ -167,9 +196,17 @@ func (p *Process) CreateTime() (int64, error) { return start.Unix() * 1000, nil } func (p *Process) Cwd() (string, error) { + return p.CwdWithContext(context.Background()) +} + +func (p *Process) CwdWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Parent() (*Process, error) { + return p.ParentWithContext(context.Background()) +} + +func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) { rr, err := common.CallLsof(invoke, p.Pid, "-FR") if err != nil { return nil, err @@ -188,6 +225,10 @@ func (p *Process) Parent() (*Process, error) { return nil, fmt.Errorf("could not find parent line") } func (p *Process) Status() (string, error) { + return p.StatusWithContext(context.Background()) +} + +func (p *Process) StatusWithContext(ctx context.Context) (string, error) { r, err := callPs("state", p.Pid, false) if err != nil { return "", err @@ -196,6 +237,10 @@ func (p *Process) Status() (string, error) { return r[0][0], err } func (p *Process) Uids() ([]int32, error) { + return p.UidsWithContext(context.Background()) +} + +func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) { k, err := p.getKProc() if err != nil { return nil, err @@ -207,6 +252,10 @@ func (p *Process) Uids() ([]int32, error) { return []int32{userEffectiveUID}, nil } func (p *Process) Gids() ([]int32, error) { + return p.GidsWithContext(context.Background()) +} + +func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) { k, err := p.getKProc() if err != nil { return nil, err @@ -218,6 +267,10 @@ func (p *Process) Gids() ([]int32, error) { return gids, nil } func (p *Process) Terminal() (string, error) { + return p.TerminalWithContext(context.Background()) +} + +func (p *Process) TerminalWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError /* k, err := p.getKProc() @@ -235,6 +288,10 @@ func (p *Process) Terminal() (string, error) { */ } func (p *Process) Nice() (int32, error) { + return p.NiceWithContext(context.Background()) +} + +func (p *Process) NiceWithContext(ctx context.Context) (int32, error) { k, err := p.getKProc() if err != nil { return 0, err @@ -242,26 +299,54 @@ func (p *Process) Nice() (int32, error) { return int32(k.Proc.P_nice), nil } func (p *Process) IOnice() (int32, error) { + return p.IOniceWithContext(context.Background()) +} + +func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) Rlimit() ([]RlimitStat, error) { + return p.RlimitWithContext(context.Background()) +} + +func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) { var rlimit []RlimitStat return rlimit, common.ErrNotImplementedError } -func (p *Process) RlimitUsage(_ bool) ([]RlimitStat, error) { +func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) { + return p.RlimitUsageWithContext(context.Background(), gatherUsed) +} + +func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) { var rlimit []RlimitStat return rlimit, common.ErrNotImplementedError } func (p *Process) IOCounters() (*IOCountersStat, error) { + return p.IOCountersWithContext(context.Background()) +} + +func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) { + return p.NumCtxSwitchesWithContext(context.Background()) +} + +func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NumFDs() (int32, error) { + return p.NumFDsWithContext(context.Background()) +} + +func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) NumThreads() (int32, error) { + return p.NumThreadsWithContext(context.Background()) +} + +func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) { r, err := callPs("utime,stime", p.Pid, true) if err != nil { return 0, err @@ -269,6 +354,10 @@ func (p *Process) NumThreads() (int32, error) { return int32(len(r)), nil } func (p *Process) Threads() (map[int32]*cpu.TimesStat, error) { + return p.ThreadsWithContext(context.Background()) +} + +func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) { ret := make(map[int32]*cpu.TimesStat) return ret, common.ErrNotImplementedError } @@ -299,6 +388,10 @@ func convertCPUTimes(s string) (ret float64, err error) { return float64(t) / ClockTicks, nil } func (p *Process) Times() (*cpu.TimesStat, error) { + return p.TimesWithContext(context.Background()) +} + +func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) { r, err := callPs("utime,stime", p.Pid, false) if err != nil { @@ -322,9 +415,17 @@ func (p *Process) Times() (*cpu.TimesStat, error) { return ret, nil } func (p *Process) CPUAffinity() ([]int32, error) { + return p.CPUAffinityWithContext(context.Background()) +} + +func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) { return nil, common.ErrNotImplementedError } func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { + return p.MemoryInfoWithContext(context.Background()) +} + +func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) { r, err := callPs("rss,vsize,pagein", p.Pid, false) if err != nil { return nil, err @@ -351,10 +452,18 @@ func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { return ret, nil } func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) { + return p.MemoryInfoExWithContext(context.Background()) +} + +func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Children() ([]*Process, error) { + return p.ChildrenWithContext(context.Background()) +} + +func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) { pids, err := common.CallPgrep(invoke, p.Pid) if err != nil { return nil, err @@ -371,21 +480,41 @@ func (p *Process) Children() ([]*Process, error) { } func (p *Process) OpenFiles() ([]OpenFilesStat, error) { + return p.OpenFilesWithContext(context.Background()) +} + +func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Connections() ([]net.ConnectionStat, error) { + return p.ConnectionsWithContext(context.Background()) +} + +func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) { return net.ConnectionsPid("all", p.Pid) } func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { + return p.NetIOCountersWithContext(context.Background(), pernic) +} + +func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]net.IOCountersStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) IsRunning() (bool, error) { + return p.IsRunningWithContext(context.Background()) +} + +func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) { return true, common.ErrNotImplementedError } func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { + return p.MemoryMapsWithContext(context.Background(), grouped) +} + +func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) { var ret []MemoryMapsStat return &ret, common.ErrNotImplementedError } @@ -436,6 +565,10 @@ func parseKinfoProc(buf []byte) (KinfoProc, error) { // Returns a proc as defined here: // http://unix.superglobalmegacorp.com/Net2/newsrc/sys/kinfo_proc.h.html func (p *Process) getKProc() (*KinfoProc, error) { + return p.getKProcWithContext(context.Background()) +} + +func (p *Process) getKProcWithContext(ctx context.Context) (*KinfoProc, error) { mib := []int32{CTLKern, KernProc, KernProcPID, p.Pid} procK := KinfoProc{} length := uint64(unsafe.Sizeof(procK)) diff --git a/process/process_fallback.go b/process/process_fallback.go index 12bd3a6..bc3bb1d 100644 --- a/process/process_fallback.go +++ b/process/process_fallback.go @@ -3,6 +3,7 @@ package process import ( + "context" "syscall" "github.com/shirou/gopsutil/cpu" @@ -28,6 +29,10 @@ type MemoryInfoExStat struct { } func Pids() ([]int32, error) { + return PidsWithContext(context.Background()) +} + +func PidsWithContext(ctx context.Context) ([]int32, error) { return []int32{}, common.ErrNotImplementedError } @@ -36,113 +41,261 @@ func NewProcess(pid int32) (*Process, error) { } func (p *Process) Ppid() (int32, error) { + return p.PpidWithContext(context.Background()) +} + +func (p *Process) PpidWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) Name() (string, error) { + return p.NameWithContext(context.Background()) +} + +func (p *Process) NameWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Exe() (string, error) { + return p.ExeWithContext(context.Background()) +} + +func (p *Process) ExeWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Cmdline() (string, error) { + return p.CmdlineWithContext(context.Background()) +} + +func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } func (p *Process) CmdlineSlice() ([]string, error) { + return p.CmdlineSliceWithContext(context.Background()) +} + +func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) { return []string{}, common.ErrNotImplementedError } func (p *Process) CreateTime() (int64, error) { + return p.CreateTimeWithContext(context.Background()) +} + +func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) { return 0, common.ErrNotImplementedError } func (p *Process) Cwd() (string, error) { + return p.CwdWithContext(context.Background()) +} + +func (p *Process) CwdWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Parent() (*Process, error) { + return p.ParentWithContext(context.Background()) +} + +func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) { return nil, common.ErrNotImplementedError } func (p *Process) Status() (string, error) { + return p.StatusWithContext(context.Background()) +} + +func (p *Process) StatusWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Uids() ([]int32, error) { + return p.UidsWithContext(context.Background()) +} + +func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) { return []int32{}, common.ErrNotImplementedError } func (p *Process) Gids() ([]int32, error) { + return p.GidsWithContext(context.Background()) +} + +func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) { return []int32{}, common.ErrNotImplementedError } func (p *Process) Terminal() (string, error) { + return p.TerminalWithContext(context.Background()) +} + +func (p *Process) TerminalWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Nice() (int32, error) { + return p.NiceWithContext(context.Background()) +} + +func (p *Process) NiceWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) IOnice() (int32, error) { + return p.IOniceWithContext(context.Background()) +} + +func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) Rlimit() ([]RlimitStat, error) { + return p.RlimitWithContext(context.Background()) +} + +func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) { return nil, common.ErrNotImplementedError } -func (p *Process) RlimitUsage(_ bool) ([]RlimitStat, error) { +func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) { + return p.RlimitUsageWithContext(context.Background(), gatherUsed) +} + +func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) IOCounters() (*IOCountersStat, error) { + return p.IOCountersWithContext(context.Background()) +} + +func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) { + return p.NumCtxSwitchesWithContext(context.Background()) +} + +func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NumFDs() (int32, error) { + return p.NumFDsWithContext(context.Background()) +} + +func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) NumThreads() (int32, error) { + return p.NumThreadsWithContext(context.Background()) +} + +func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) Threads() (map[int32]*cpu.TimesStat, error) { + return p.ThreadsWithContext(context.Background()) +} + +func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Times() (*cpu.TimesStat, error) { + return p.TimesWithContext(context.Background()) +} + +func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) CPUAffinity() ([]int32, error) { + return p.CPUAffinityWithContext(context.Background()) +} + +func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) { return nil, common.ErrNotImplementedError } func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { + return p.MemoryInfoWithContext(context.Background()) +} + +func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) { + return p.MemoryInfoExWithContext(context.Background()) +} + +func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Children() ([]*Process, error) { + return p.ChildrenWithContext(context.Background()) +} + +func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) { return nil, common.ErrNotImplementedError } func (p *Process) OpenFiles() ([]OpenFilesStat, error) { + return p.OpenFilesWithContext(context.Background()) +} + +func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) { return []OpenFilesStat{}, common.ErrNotImplementedError } func (p *Process) Connections() ([]net.ConnectionStat, error) { + return p.ConnectionsWithContext(context.Background()) +} + +func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) { return []net.ConnectionStat{}, common.ErrNotImplementedError } func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { + return p.NetIOCountersWithContext(context.Background(), pernic) +} + +func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]net.IOCountersStat, error) { return []net.IOCountersStat{}, common.ErrNotImplementedError } func (p *Process) IsRunning() (bool, error) { + return p.IsRunningWithContext(context.Background()) +} + +func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) { return true, common.ErrNotImplementedError } func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { + return p.MemoryMapsWithContext(context.Background(), grouped) +} + +func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) SendSignal(sig syscall.Signal) error { + return p.SendSignalWithContext(context.Background(), sig) +} + +func (p *Process) SendSignalWithContext(ctx context.Context, sig syscall.Signal) error { return common.ErrNotImplementedError } func (p *Process) Suspend() error { + return p.SuspendWithContext(context.Background()) +} + +func (p *Process) SuspendWithContext(ctx context.Context) error { return common.ErrNotImplementedError } func (p *Process) Resume() error { + return p.ResumeWithContext(context.Background()) +} + +func (p *Process) ResumeWithContext(ctx context.Context) error { return common.ErrNotImplementedError } func (p *Process) Terminate() error { + return p.TerminateWithContext(context.Background()) +} + +func (p *Process) TerminateWithContext(ctx context.Context) error { return common.ErrNotImplementedError } func (p *Process) Kill() error { + return p.KillWithContext(context.Background()) +} + +func (p *Process) KillWithContext(ctx context.Context) error { return common.ErrNotImplementedError } func (p *Process) Username() (string, error) { + return p.UsernameWithContext(context.Background()) +} + +func (p *Process) UsernameWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } diff --git a/process/process_freebsd.go b/process/process_freebsd.go index 9d75717..7b85e8a 100644 --- a/process/process_freebsd.go +++ b/process/process_freebsd.go @@ -4,6 +4,7 @@ package process import ( "bytes" + "context" "encoding/binary" "strings" @@ -21,6 +22,10 @@ type MemoryMapsStat struct { } func Pids() ([]int32, error) { + return PidsWithContext(context.Background()) +} + +func PidsWithContext(ctx context.Context) ([]int32, error) { var ret []int32 procs, err := Processes() if err != nil { @@ -35,6 +40,10 @@ func Pids() ([]int32, error) { } func (p *Process) Ppid() (int32, error) { + return p.PpidWithContext(context.Background()) +} + +func (p *Process) PpidWithContext(ctx context.Context) (int32, error) { k, err := p.getKProc() if err != nil { return 0, err @@ -43,6 +52,10 @@ func (p *Process) Ppid() (int32, error) { return k.Ppid, nil } func (p *Process) Name() (string, error) { + return p.NameWithContext(context.Background()) +} + +func (p *Process) NameWithContext(ctx context.Context) (string, error) { k, err := p.getKProc() if err != nil { return "", err @@ -51,10 +64,18 @@ func (p *Process) Name() (string, error) { return common.IntToString(k.Comm[:]), nil } func (p *Process) Exe() (string, error) { + return p.ExeWithContext(context.Background()) +} + +func (p *Process) ExeWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Cmdline() (string, error) { + return p.CmdlineWithContext(context.Background()) +} + +func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) { mib := []int32{CTLKern, KernProc, KernProcArgs, p.Pid} buf, _, err := common.CallSyscall(mib) if err != nil { @@ -71,6 +92,10 @@ func (p *Process) Cmdline() (string, error) { } func (p *Process) CmdlineSlice() ([]string, error) { + return p.CmdlineSliceWithContext(context.Background()) +} + +func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) { mib := []int32{CTLKern, KernProc, KernProcArgs, p.Pid} buf, _, err := common.CallSyscall(mib) if err != nil { @@ -91,15 +116,31 @@ func (p *Process) CmdlineSlice() ([]string, error) { return strParts, nil } func (p *Process) CreateTime() (int64, error) { + return p.CreateTimeWithContext(context.Background()) +} + +func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) { return 0, common.ErrNotImplementedError } func (p *Process) Cwd() (string, error) { + return p.CwdWithContext(context.Background()) +} + +func (p *Process) CwdWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Parent() (*Process, error) { + return p.ParentWithContext(context.Background()) +} + +func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) { return p, common.ErrNotImplementedError } func (p *Process) Status() (string, error) { + return p.StatusWithContext(context.Background()) +} + +func (p *Process) StatusWithContext(ctx context.Context) (string, error) { k, err := p.getKProc() if err != nil { return "", err @@ -125,6 +166,10 @@ func (p *Process) Status() (string, error) { return s, nil } func (p *Process) Uids() ([]int32, error) { + return p.UidsWithContext(context.Background()) +} + +func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) { k, err := p.getKProc() if err != nil { return nil, err @@ -137,6 +182,10 @@ func (p *Process) Uids() ([]int32, error) { return uids, nil } func (p *Process) Gids() ([]int32, error) { + return p.GidsWithContext(context.Background()) +} + +func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) { k, err := p.getKProc() if err != nil { return nil, err @@ -148,6 +197,10 @@ func (p *Process) Gids() ([]int32, error) { return gids, nil } func (p *Process) Terminal() (string, error) { + return p.TerminalWithContext(context.Background()) +} + +func (p *Process) TerminalWithContext(ctx context.Context) (string, error) { k, err := p.getKProc() if err != nil { return "", err @@ -163,6 +216,10 @@ func (p *Process) Terminal() (string, error) { return termmap[ttyNr], nil } func (p *Process) Nice() (int32, error) { + return p.NiceWithContext(context.Background()) +} + +func (p *Process) NiceWithContext(ctx context.Context) (int32, error) { k, err := p.getKProc() if err != nil { return 0, err @@ -170,17 +227,33 @@ func (p *Process) Nice() (int32, error) { return int32(k.Nice), nil } func (p *Process) IOnice() (int32, error) { + return p.IOniceWithContext(context.Background()) +} + +func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) Rlimit() ([]RlimitStat, error) { + return p.RlimitWithContext(context.Background()) +} + +func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) { var rlimit []RlimitStat return rlimit, common.ErrNotImplementedError } -func (p *Process) RlimitUsage(_ bool) ([]RlimitStat, error) { +func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) { + return p.RlimitUsageWithContext(context.Background(), gatherUsed) +} + +func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) { var rlimit []RlimitStat return rlimit, common.ErrNotImplementedError } func (p *Process) IOCounters() (*IOCountersStat, error) { + return p.IOCountersWithContext(context.Background()) +} + +func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) { k, err := p.getKProc() if err != nil { return nil, err @@ -191,12 +264,24 @@ func (p *Process) IOCounters() (*IOCountersStat, error) { }, nil } func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) { + return p.NumCtxSwitchesWithContext(context.Background()) +} + +func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NumFDs() (int32, error) { + return p.NumFDsWithContext(context.Background()) +} + +func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) NumThreads() (int32, error) { + return p.NumThreadsWithContext(context.Background()) +} + +func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) { k, err := p.getKProc() if err != nil { return 0, err @@ -205,10 +290,18 @@ func (p *Process) NumThreads() (int32, error) { return k.Numthreads, nil } func (p *Process) Threads() (map[int32]*cpu.TimesStat, error) { + return p.ThreadsWithContext(context.Background()) +} + +func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) { ret := make(map[int32]*cpu.TimesStat) return ret, common.ErrNotImplementedError } func (p *Process) Times() (*cpu.TimesStat, error) { + return p.TimesWithContext(context.Background()) +} + +func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) { k, err := p.getKProc() if err != nil { return nil, err @@ -220,9 +313,17 @@ func (p *Process) Times() (*cpu.TimesStat, error) { }, nil } func (p *Process) CPUAffinity() ([]int32, error) { + return p.CPUAffinityWithContext(context.Background()) +} + +func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) { return nil, common.ErrNotImplementedError } func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { + return p.MemoryInfoWithContext(context.Background()) +} + +func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) { k, err := p.getKProc() if err != nil { return nil, err @@ -239,10 +340,18 @@ func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { }, nil } func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) { + return p.MemoryInfoExWithContext(context.Background()) +} + +func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Children() ([]*Process, error) { + return p.ChildrenWithContext(context.Background()) +} + +func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) { pids, err := common.CallPgrep(invoke, p.Pid) if err != nil { return nil, err @@ -259,21 +368,41 @@ func (p *Process) Children() ([]*Process, error) { } func (p *Process) OpenFiles() ([]OpenFilesStat, error) { + return p.OpenFilesWithContext(context.Background()) +} + +func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Connections() ([]net.ConnectionStat, error) { + return p.ConnectionsWithContext(context.Background()) +} + +func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { + return p.NetIOCountersWithContext(context.Background(), pernic) +} + +func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]net.IOCountersStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) IsRunning() (bool, error) { + return p.IsRunningWithContext(context.Background()) +} + +func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) { return true, common.ErrNotImplementedError } func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { + return p.MemoryMapsWithContext(context.Background(), grouped) +} + +func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) { var ret []MemoryMapsStat return &ret, common.ErrNotImplementedError } @@ -316,6 +445,10 @@ func parseKinfoProc(buf []byte) (KinfoProc, error) { } func (p *Process) getKProc() (*KinfoProc, error) { + return p.getKProcWithContext(context.Background()) +} + +func (p *Process) getKProcWithContext(ctx context.Context) (*KinfoProc, error) { mib := []int32{CTLKern, KernProc, KernProcPID, p.Pid} buf, length, err := common.CallSyscall(mib) diff --git a/process/process_linux.go b/process/process_linux.go index 9db1997..a9aed88 100644 --- a/process/process_linux.go +++ b/process/process_linux.go @@ -5,6 +5,7 @@ package process import ( "bufio" "bytes" + "context" "encoding/json" "errors" "fmt" @@ -83,6 +84,10 @@ func NewProcess(pid int32) (*Process, error) { // Ppid returns Parent Process ID of the process. func (p *Process) Ppid() (int32, error) { + return p.PpidWithContext(context.Background()) +} + +func (p *Process) PpidWithContext(ctx context.Context) (int32, error) { _, ppid, _, _, _, _, err := p.fillFromStat() if err != nil { return -1, err @@ -92,6 +97,10 @@ func (p *Process) Ppid() (int32, error) { // Name returns name of the process. func (p *Process) Name() (string, error) { + return p.NameWithContext(context.Background()) +} + +func (p *Process) NameWithContext(ctx context.Context) (string, error) { if p.name == "" { if err := p.fillFromStatus(); err != nil { return "", err @@ -102,23 +111,39 @@ func (p *Process) Name() (string, error) { // Exe returns executable path of the process. func (p *Process) Exe() (string, error) { + return p.ExeWithContext(context.Background()) +} + +func (p *Process) ExeWithContext(ctx context.Context) (string, error) { return p.fillFromExe() } // Cmdline returns the command line arguments of the process as a string with // each argument separated by 0x20 ascii character. func (p *Process) Cmdline() (string, error) { + return p.CmdlineWithContext(context.Background()) +} + +func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) { return p.fillFromCmdline() } // CmdlineSlice returns the command line arguments of the process as a slice with each // element being an argument. func (p *Process) CmdlineSlice() ([]string, error) { + return p.CmdlineSliceWithContext(context.Background()) +} + +func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) { return p.fillSliceFromCmdline() } // CreateTime returns created time of the process in milliseconds since the epoch, in UTC. func (p *Process) CreateTime() (int64, error) { + return p.CreateTimeWithContext(context.Background()) +} + +func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) { _, _, _, createTime, _, _, err := p.fillFromStat() if err != nil { return 0, err @@ -128,11 +153,19 @@ func (p *Process) CreateTime() (int64, error) { // Cwd returns current working directory of the process. func (p *Process) Cwd() (string, error) { + return p.CwdWithContext(context.Background()) +} + +func (p *Process) CwdWithContext(ctx context.Context) (string, error) { return p.fillFromCwd() } // Parent returns parent Process of the process. func (p *Process) Parent() (*Process, error) { + return p.ParentWithContext(context.Background()) +} + +func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) { err := p.fillFromStatus() if err != nil { return nil, err @@ -149,6 +182,10 @@ func (p *Process) Parent() (*Process, error) { // Z: Zombie W: Wait L: Lock // The charactor is same within all supported platforms. func (p *Process) Status() (string, error) { + return p.StatusWithContext(context.Background()) +} + +func (p *Process) StatusWithContext(ctx context.Context) (string, error) { err := p.fillFromStatus() if err != nil { return "", err @@ -158,6 +195,10 @@ func (p *Process) Status() (string, error) { // Uids returns user ids of the process as a slice of the int func (p *Process) Uids() ([]int32, error) { + return p.UidsWithContext(context.Background()) +} + +func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) { err := p.fillFromStatus() if err != nil { return []int32{}, err @@ -167,6 +208,10 @@ func (p *Process) Uids() ([]int32, error) { // Gids returns group ids of the process as a slice of the int func (p *Process) Gids() ([]int32, error) { + return p.GidsWithContext(context.Background()) +} + +func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) { err := p.fillFromStatus() if err != nil { return []int32{}, err @@ -176,6 +221,10 @@ func (p *Process) Gids() ([]int32, error) { // Terminal returns a terminal which is associated with the process. func (p *Process) Terminal() (string, error) { + return p.TerminalWithContext(context.Background()) +} + +func (p *Process) TerminalWithContext(ctx context.Context) (string, error) { terminal, _, _, _, _, _, err := p.fillFromStat() if err != nil { return "", err @@ -186,6 +235,10 @@ func (p *Process) Terminal() (string, error) { // Nice returns a nice value (priority). // Notice: gopsutil can not set nice value. func (p *Process) Nice() (int32, error) { + return p.NiceWithContext(context.Background()) +} + +func (p *Process) NiceWithContext(ctx context.Context) (int32, error) { _, _, _, _, _, nice, err := p.fillFromStat() if err != nil { return 0, err @@ -195,11 +248,19 @@ func (p *Process) Nice() (int32, error) { // IOnice returns process I/O nice value (priority). func (p *Process) IOnice() (int32, error) { + return p.IOniceWithContext(context.Background()) +} + +func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError } // Rlimit returns Resource Limits. func (p *Process) Rlimit() ([]RlimitStat, error) { + return p.RlimitWithContext(context.Background()) +} + +func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) { return p.RlimitUsage(false) } @@ -207,6 +268,10 @@ func (p *Process) Rlimit() ([]RlimitStat, error) { // If gatherUsed is true, the currently used value will be gathered and added // to the resulting RlimitStat. func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) { + return p.RlimitUsageWithContext(context.Background(), gatherUsed) +} + +func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) { rlimits, err := p.fillFromLimits() if !gatherUsed || err != nil { return rlimits, err @@ -263,11 +328,19 @@ func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) { // IOCounters returns IO Counters. func (p *Process) IOCounters() (*IOCountersStat, error) { + return p.IOCountersWithContext(context.Background()) +} + +func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) { return p.fillFromIO() } // NumCtxSwitches returns the number of the context switches of the process. func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) { + return p.NumCtxSwitchesWithContext(context.Background()) +} + +func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) { err := p.fillFromStatus() if err != nil { return nil, err @@ -277,12 +350,20 @@ func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) { // NumFDs returns the number of File Descriptors used by the process. func (p *Process) NumFDs() (int32, error) { + return p.NumFDsWithContext(context.Background()) +} + +func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) { _, fnames, err := p.fillFromfdList() return int32(len(fnames)), err } // NumThreads returns the number of threads used by the process. func (p *Process) NumThreads() (int32, error) { + return p.NumThreadsWithContext(context.Background()) +} + +func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) { err := p.fillFromStatus() if err != nil { return 0, err @@ -291,6 +372,10 @@ func (p *Process) NumThreads() (int32, error) { } func (p *Process) Threads() (map[int32]*cpu.TimesStat, error) { + return p.ThreadsWithContext(context.Background()) +} + +func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) { ret := make(map[int32]*cpu.TimesStat) taskPath := common.HostProc(strconv.Itoa(int(p.Pid)), "task") @@ -312,6 +397,10 @@ func (p *Process) Threads() (map[int32]*cpu.TimesStat, error) { // Times returns CPU times of the process. func (p *Process) Times() (*cpu.TimesStat, error) { + return p.TimesWithContext(context.Background()) +} + +func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) { _, _, cpuTimes, _, _, _, err := p.fillFromStat() if err != nil { return nil, err @@ -323,11 +412,19 @@ func (p *Process) Times() (*cpu.TimesStat, error) { // // Notice: Not implemented yet. func (p *Process) CPUAffinity() ([]int32, error) { + return p.CPUAffinityWithContext(context.Background()) +} + +func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) { return nil, common.ErrNotImplementedError } // MemoryInfo returns platform in-dependend memory information, such as RSS, VMS and Swap func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { + return p.MemoryInfoWithContext(context.Background()) +} + +func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) { meminfo, _, err := p.fillFromStatm() if err != nil { return nil, err @@ -337,6 +434,10 @@ func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { // MemoryInfoEx returns platform dependend memory information. func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) { + return p.MemoryInfoExWithContext(context.Background()) +} + +func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) { _, memInfoEx, err := p.fillFromStatm() if err != nil { return nil, err @@ -346,6 +447,10 @@ func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) { // Children returns a slice of Process of the process. func (p *Process) Children() ([]*Process, error) { + return p.ChildrenWithContext(context.Background()) +} + +func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) { pids, err := common.CallPgrep(invoke, p.Pid) if err != nil { if pids == nil || len(pids) == 0 { @@ -367,6 +472,10 @@ func (p *Process) Children() ([]*Process, error) { // OpenFiles returns a slice of OpenFilesStat opend by the process. // OpenFilesStat includes a file path and file descriptor. func (p *Process) OpenFiles() ([]OpenFilesStat, error) { + return p.OpenFilesWithContext(context.Background()) +} + +func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) { _, ofs, err := p.fillFromfd() if err != nil { return nil, err @@ -382,11 +491,19 @@ func (p *Process) OpenFiles() ([]OpenFilesStat, error) { // Connections returns a slice of net.ConnectionStat used by the process. // This returns all kind of the connection. This measn TCP, UDP or UNIX. func (p *Process) Connections() ([]net.ConnectionStat, error) { + return p.ConnectionsWithContext(context.Background()) +} + +func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) { return net.ConnectionsPid("all", p.Pid) } // NetIOCounters returns NetIOCounters of the process. func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { + return p.NetIOCountersWithContext(context.Background(), pernic) +} + +func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]net.IOCountersStat, error) { filename := common.HostProc(strconv.Itoa(int(p.Pid)), "net/dev") return net.IOCountersByFile(pernic, filename) } @@ -394,11 +511,19 @@ func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { // IsRunning returns whether the process is running or not. // Not implemented yet. func (p *Process) IsRunning() (bool, error) { + return p.IsRunningWithContext(context.Background()) +} + +func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) { return true, common.ErrNotImplementedError } // MemoryMaps get memory maps from /proc/(pid)/smaps func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { + return p.MemoryMapsWithContext(context.Background(), grouped) +} + +func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) { pid := p.Pid var ret []MemoryMapsStat smapsPath := common.HostProc(strconv.Itoa(int(pid)), "smaps") @@ -493,6 +618,10 @@ func limitToInt(val string) (int32, error) { // Get num_fds from /proc/(pid)/limits func (p *Process) fillFromLimits() ([]RlimitStat, error) { + return p.fillFromLimitsWithContext(context.Background()) +} + +func (p *Process) fillFromLimitsWithContext(ctx context.Context) ([]RlimitStat, error) { pid := p.Pid limitsFile := common.HostProc(strconv.Itoa(int(pid)), "limits") d, err := os.Open(limitsFile) @@ -586,6 +715,10 @@ func (p *Process) fillFromLimits() ([]RlimitStat, error) { // Get list of /proc/(pid)/fd files func (p *Process) fillFromfdList() (string, []string, error) { + return p.fillFromfdListWithContext(context.Background()) +} + +func (p *Process) fillFromfdListWithContext(ctx context.Context) (string, []string, error) { pid := p.Pid statPath := common.HostProc(strconv.Itoa(int(pid)), "fd") d, err := os.Open(statPath) @@ -599,6 +732,10 @@ func (p *Process) fillFromfdList() (string, []string, error) { // Get num_fds from /proc/(pid)/fd func (p *Process) fillFromfd() (int32, []*OpenFilesStat, error) { + return p.fillFromfdWithContext(context.Background()) +} + +func (p *Process) fillFromfdWithContext(ctx context.Context) (int32, []*OpenFilesStat, error) { statPath, fnames, err := p.fillFromfdList() if err != nil { return 0, nil, err @@ -628,6 +765,10 @@ func (p *Process) fillFromfd() (int32, []*OpenFilesStat, error) { // Get cwd from /proc/(pid)/cwd func (p *Process) fillFromCwd() (string, error) { + return p.fillFromCwdWithContext(context.Background()) +} + +func (p *Process) fillFromCwdWithContext(ctx context.Context) (string, error) { pid := p.Pid cwdPath := common.HostProc(strconv.Itoa(int(pid)), "cwd") cwd, err := os.Readlink(cwdPath) @@ -639,6 +780,10 @@ func (p *Process) fillFromCwd() (string, error) { // Get exe from /proc/(pid)/exe func (p *Process) fillFromExe() (string, error) { + return p.fillFromExeWithContext(context.Background()) +} + +func (p *Process) fillFromExeWithContext(ctx context.Context) (string, error) { pid := p.Pid exePath := common.HostProc(strconv.Itoa(int(pid)), "exe") exe, err := os.Readlink(exePath) @@ -650,6 +795,10 @@ func (p *Process) fillFromExe() (string, error) { // Get cmdline from /proc/(pid)/cmdline func (p *Process) fillFromCmdline() (string, error) { + return p.fillFromCmdlineWithContext(context.Background()) +} + +func (p *Process) fillFromCmdlineWithContext(ctx context.Context) (string, error) { pid := p.Pid cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline") cmdline, err := ioutil.ReadFile(cmdPath) @@ -667,6 +816,10 @@ func (p *Process) fillFromCmdline() (string, error) { } func (p *Process) fillSliceFromCmdline() ([]string, error) { + return p.fillSliceFromCmdlineWithContext(context.Background()) +} + +func (p *Process) fillSliceFromCmdlineWithContext(ctx context.Context) ([]string, error) { pid := p.Pid cmdPath := common.HostProc(strconv.Itoa(int(pid)), "cmdline") cmdline, err := ioutil.ReadFile(cmdPath) @@ -690,6 +843,10 @@ func (p *Process) fillSliceFromCmdline() ([]string, error) { // Get IO status from /proc/(pid)/io func (p *Process) fillFromIO() (*IOCountersStat, error) { + return p.fillFromIOWithContext(context.Background()) +} + +func (p *Process) fillFromIOWithContext(ctx context.Context) (*IOCountersStat, error) { pid := p.Pid ioPath := common.HostProc(strconv.Itoa(int(pid)), "io") ioline, err := ioutil.ReadFile(ioPath) @@ -729,6 +886,10 @@ func (p *Process) fillFromIO() (*IOCountersStat, error) { // Get memory info from /proc/(pid)/statm func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) { + return p.fillFromStatmWithContext(context.Background()) +} + +func (p *Process) fillFromStatmWithContext(ctx context.Context) (*MemoryInfoStat, *MemoryInfoExStat, error) { pid := p.Pid memPath := common.HostProc(strconv.Itoa(int(pid)), "statm") contents, err := ioutil.ReadFile(memPath) @@ -781,6 +942,10 @@ func (p *Process) fillFromStatm() (*MemoryInfoStat, *MemoryInfoExStat, error) { // Get various status from /proc/(pid)/status func (p *Process) fillFromStatus() error { + return p.fillFromStatusWithContext(context.Background()) +} + +func (p *Process) fillFromStatusWithContext(ctx context.Context) error { pid := p.Pid statPath := common.HostProc(strconv.Itoa(int(pid)), "status") contents, err := ioutil.ReadFile(statPath) @@ -935,6 +1100,10 @@ func (p *Process) fillFromStatus() error { } func (p *Process) fillFromTIDStat(tid int32) (string, int32, *cpu.TimesStat, int64, uint32, int32, error) { + return p.fillFromTIDStatWithContext(context.Background(), tid) +} + +func (p *Process) fillFromTIDStatWithContext(ctx context.Context, tid int32) (string, int32, *cpu.TimesStat, int64, uint32, int32, error) { pid := p.Pid var statPath string @@ -1009,11 +1178,19 @@ func (p *Process) fillFromTIDStat(tid int32) (string, int32, *cpu.TimesStat, int } func (p *Process) fillFromStat() (string, int32, *cpu.TimesStat, int64, uint32, int32, error) { + return p.fillFromStatWithContext(context.Background()) +} + +func (p *Process) fillFromStatWithContext(ctx context.Context) (string, int32, *cpu.TimesStat, int64, uint32, int32, error) { return p.fillFromTIDStat(-1) } // Pids returns a slice of process ID list which are running now. func Pids() ([]int32, error) { + return PidsWithContext(context.Background()) +} + +func PidsWithContext(ctx context.Context) ([]int32, error) { return readPidsFromDir(common.HostProc()) } diff --git a/process/process_openbsd.go b/process/process_openbsd.go index aca4ffa..2a8eec7 100644 --- a/process/process_openbsd.go +++ b/process/process_openbsd.go @@ -15,6 +15,7 @@ import ( net "github.com/shirou/gopsutil/net" "golang.org/x/sys/unix" ) +import "context" // MemoryInfoExStat is different between OSes type MemoryInfoExStat struct { @@ -24,6 +25,10 @@ type MemoryMapsStat struct { } func Pids() ([]int32, error) { + return PidsWithContext(context.Background()) +} + +func PidsWithContext(ctx context.Context) ([]int32, error) { var ret []int32 procs, err := Processes() if err != nil { @@ -38,6 +43,10 @@ func Pids() ([]int32, error) { } func (p *Process) Ppid() (int32, error) { + return p.PpidWithContext(context.Background()) +} + +func (p *Process) PpidWithContext(ctx context.Context) (int32, error) { k, err := p.getKProc() if err != nil { return 0, err @@ -46,6 +55,10 @@ func (p *Process) Ppid() (int32, error) { return k.Ppid, nil } func (p *Process) Name() (string, error) { + return p.NameWithContext(context.Background()) +} + +func (p *Process) NameWithContext(ctx context.Context) (string, error) { k, err := p.getKProc() if err != nil { return "", err @@ -54,10 +67,18 @@ func (p *Process) Name() (string, error) { return common.IntToString(k.Comm[:]), nil } func (p *Process) Exe() (string, error) { + return p.ExeWithContext(context.Background()) +} + +func (p *Process) ExeWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } func (p *Process) CmdlineSlice() ([]string, error) { + return p.CmdlineSliceWithContext(context.Background()) +} + +func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) { mib := []int32{CTLKern, KernProcArgs, p.Pid, KernProcArgv} buf, _, err := common.CallSyscall(mib) @@ -81,6 +102,10 @@ func (p *Process) CmdlineSlice() ([]string, error) { } func (p *Process) Cmdline() (string, error) { + return p.CmdlineWithContext(context.Background()) +} + +func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) { argv, err := p.CmdlineSlice() if err != nil { return "", err @@ -89,15 +114,31 @@ func (p *Process) Cmdline() (string, error) { } func (p *Process) CreateTime() (int64, error) { + return p.CreateTimeWithContext(context.Background()) +} + +func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) { return 0, common.ErrNotImplementedError } func (p *Process) Cwd() (string, error) { + return p.CwdWithContext(context.Background()) +} + +func (p *Process) CwdWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Parent() (*Process, error) { + return p.ParentWithContext(context.Background()) +} + +func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) { return p, common.ErrNotImplementedError } func (p *Process) Status() (string, error) { + return p.StatusWithContext(context.Background()) +} + +func (p *Process) StatusWithContext(ctx context.Context) (string, error) { k, err := p.getKProc() if err != nil { return "", err @@ -119,6 +160,10 @@ func (p *Process) Status() (string, error) { return s, nil } func (p *Process) Uids() ([]int32, error) { + return p.UidsWithContext(context.Background()) +} + +func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) { k, err := p.getKProc() if err != nil { return nil, err @@ -131,6 +176,10 @@ func (p *Process) Uids() ([]int32, error) { return uids, nil } func (p *Process) Gids() ([]int32, error) { + return p.GidsWithContext(context.Background()) +} + +func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) { k, err := p.getKProc() if err != nil { return nil, err @@ -142,6 +191,10 @@ func (p *Process) Gids() ([]int32, error) { return gids, nil } func (p *Process) Terminal() (string, error) { + return p.TerminalWithContext(context.Background()) +} + +func (p *Process) TerminalWithContext(ctx context.Context) (string, error) { k, err := p.getKProc() if err != nil { return "", err @@ -157,6 +210,10 @@ func (p *Process) Terminal() (string, error) { return termmap[ttyNr], nil } func (p *Process) Nice() (int32, error) { + return p.NiceWithContext(context.Background()) +} + +func (p *Process) NiceWithContext(ctx context.Context) (int32, error) { k, err := p.getKProc() if err != nil { return 0, err @@ -164,17 +221,33 @@ func (p *Process) Nice() (int32, error) { return int32(k.Nice), nil } func (p *Process) IOnice() (int32, error) { + return p.IOniceWithContext(context.Background()) +} + +func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) Rlimit() ([]RlimitStat, error) { + return p.RlimitWithContext(context.Background()) +} + +func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) { var rlimit []RlimitStat return rlimit, common.ErrNotImplementedError } -func (p *Process) RlimitUsage(_ bool) ([]RlimitStat, error) { +func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) { + return p.RlimitUsageWithContext(context.Background(), gatherUsed) +} + +func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) { var rlimit []RlimitStat return rlimit, common.ErrNotImplementedError } func (p *Process) IOCounters() (*IOCountersStat, error) { + return p.IOCountersWithContext(context.Background()) +} + +func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) { k, err := p.getKProc() if err != nil { return nil, err @@ -185,20 +258,40 @@ func (p *Process) IOCounters() (*IOCountersStat, error) { }, nil } func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) { + return p.NumCtxSwitchesWithContext(context.Background()) +} + +func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NumFDs() (int32, error) { + return p.NumFDsWithContext(context.Background()) +} + +func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) NumThreads() (int32, error) { + return p.NumThreadsWithContext(context.Background()) +} + +func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) { /* not supported, just return 1 */ return 1, nil } func (p *Process) Threads() (map[int32]*cpu.TimesStat, error) { + return p.ThreadsWithContext(context.Background()) +} + +func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) { ret := make(map[int32]*cpu.TimesStat) return ret, common.ErrNotImplementedError } func (p *Process) Times() (*cpu.TimesStat, error) { + return p.TimesWithContext(context.Background()) +} + +func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) { k, err := p.getKProc() if err != nil { return nil, err @@ -210,9 +303,17 @@ func (p *Process) Times() (*cpu.TimesStat, error) { }, nil } func (p *Process) CPUAffinity() ([]int32, error) { + return p.CPUAffinityWithContext(context.Background()) +} + +func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) { return nil, common.ErrNotImplementedError } func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { + return p.MemoryInfoWithContext(context.Background()) +} + +func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) { k, err := p.getKProc() if err != nil { return nil, err @@ -229,10 +330,18 @@ func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { }, nil } func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) { + return p.MemoryInfoExWithContext(context.Background()) +} + +func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Children() ([]*Process, error) { + return p.ChildrenWithContext(context.Background()) +} + +func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) { pids, err := common.CallPgrep(invoke, p.Pid) if err != nil { return nil, err @@ -249,21 +358,41 @@ func (p *Process) Children() ([]*Process, error) { } func (p *Process) OpenFiles() ([]OpenFilesStat, error) { + return p.OpenFilesWithContext(context.Background()) +} + +func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Connections() ([]net.ConnectionStat, error) { + return p.ConnectionsWithContext(context.Background()) +} + +func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { + return p.NetIOCountersWithContext(context.Background(), pernic) +} + +func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]net.IOCountersStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) IsRunning() (bool, error) { + return p.IsRunningWithContext(context.Background()) +} + +func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) { return true, common.ErrNotImplementedError } func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { + return p.MemoryMapsWithContext(context.Background(), grouped) +} + +func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) { var ret []MemoryMapsStat return &ret, common.ErrNotImplementedError } @@ -306,6 +435,10 @@ func parseKinfoProc(buf []byte) (KinfoProc, error) { } func (p *Process) getKProc() (*KinfoProc, error) { + return p.getKProcWithContext(context.Background()) +} + +func (p *Process) getKProcWithContext(ctx context.Context) (*KinfoProc, error) { buf, length, err := CallKernProcSyscall(KernProcPID, p.Pid) if err != nil { return nil, err @@ -328,6 +461,10 @@ func NewProcess(pid int32) (*Process, error) { } func CallKernProcSyscall(op int32, arg int32) ([]byte, uint64, error) { + return CallKernProcSyscallWithContext(context.Background(), op, arg) +} + +func CallKernProcSyscallWithContext(ctx context.Context, op int32, arg int32) ([]byte, uint64, error) { mib := []int32{CTLKern, KernProc, op, arg, sizeOfKinfoProc, 0} mibptr := unsafe.Pointer(&mib[0]) miblen := uint64(len(mib)) diff --git a/process/process_posix.go b/process/process_posix.go index 55c9c00..d058278 100644 --- a/process/process_posix.go +++ b/process/process_posix.go @@ -3,6 +3,7 @@ package process import ( + "context" "os" "os/user" "path/filepath" @@ -65,6 +66,10 @@ func getTerminalMap() (map[uint64]string, error) { // SendSignal sends a unix.Signal to the process. // Currently, SIGSTOP, SIGCONT, SIGTERM and SIGKILL are supported. func (p *Process) SendSignal(sig syscall.Signal) error { + return p.SendSignalWithContext(context.Background(), sig) +} + +func (p *Process) SendSignalWithContext(ctx context.Context, sig syscall.Signal) error { process, err := os.FindProcess(int(p.Pid)) if err != nil { return err @@ -80,26 +85,46 @@ func (p *Process) SendSignal(sig syscall.Signal) error { // Suspend sends SIGSTOP to the process. func (p *Process) Suspend() error { + return p.SuspendWithContext(context.Background()) +} + +func (p *Process) SuspendWithContext(ctx context.Context) error { return p.SendSignal(unix.SIGSTOP) } // Resume sends SIGCONT to the process. func (p *Process) Resume() error { + return p.ResumeWithContext(context.Background()) +} + +func (p *Process) ResumeWithContext(ctx context.Context) error { return p.SendSignal(unix.SIGCONT) } // Terminate sends SIGTERM to the process. func (p *Process) Terminate() error { + return p.TerminateWithContext(context.Background()) +} + +func (p *Process) TerminateWithContext(ctx context.Context) error { return p.SendSignal(unix.SIGTERM) } // Kill sends SIGKILL to the process. func (p *Process) Kill() error { + return p.KillWithContext(context.Background()) +} + +func (p *Process) KillWithContext(ctx context.Context) error { return p.SendSignal(unix.SIGKILL) } // Username returns a username of the process. func (p *Process) Username() (string, error) { + return p.UsernameWithContext(context.Background()) +} + +func (p *Process) UsernameWithContext(ctx context.Context) (string, error) { uids, err := p.Uids() if err != nil { return "", err diff --git a/process/process_windows.go b/process/process_windows.go index 3ce840b..c875ec2 100644 --- a/process/process_windows.go +++ b/process/process_windows.go @@ -95,6 +95,10 @@ func init() { } func Pids() ([]int32, error) { + return PidsWithContext(context.Background()) +} + +func PidsWithContext(ctx context.Context) ([]int32, error) { // inspired by https://gist.github.com/henkman/3083408 // and https://github.com/giampaolo/psutil/blob/1c3a15f637521ba5c0031283da39c733fda53e4c/psutil/arch/windows/process_info.c#L315-L329 var ret []int32 @@ -121,6 +125,10 @@ func Pids() ([]int32, error) { } func (p *Process) Ppid() (int32, error) { + return p.PpidWithContext(context.Background()) +} + +func (p *Process) PpidWithContext(ctx context.Context) (int32, error) { ppid, _, _, err := getFromSnapProcess(p.Pid) if err != nil { return 0, err @@ -129,6 +137,10 @@ func (p *Process) Ppid() (int32, error) { } func GetWin32Proc(pid int32) ([]Win32_Process, error) { + return GetWin32ProcWithContext(context.Background(), pid) +} + +func GetWin32ProcWithContext(ctx context.Context, pid int32) ([]Win32_Process, error) { var dst []Win32_Process query := fmt.Sprintf("WHERE ProcessId = %d", pid) q := wmi.CreateQuery(&dst, query) @@ -147,6 +159,10 @@ func GetWin32Proc(pid int32) ([]Win32_Process, error) { } func (p *Process) Name() (string, error) { + return p.NameWithContext(context.Background()) +} + +func (p *Process) NameWithContext(ctx context.Context) (string, error) { _, _, name, err := getFromSnapProcess(p.Pid) if err != nil { return "", fmt.Errorf("could not get Name: %s", err) @@ -155,6 +171,10 @@ func (p *Process) Name() (string, error) { } func (p *Process) Exe() (string, error) { + return p.ExeWithContext(context.Background()) +} + +func (p *Process) ExeWithContext(ctx context.Context) (string, error) { dst, err := GetWin32Proc(p.Pid) if err != nil { return "", fmt.Errorf("could not get ExecutablePath: %s", err) @@ -163,6 +183,10 @@ func (p *Process) Exe() (string, error) { } func (p *Process) Cmdline() (string, error) { + return p.CmdlineWithContext(context.Background()) +} + +func (p *Process) CmdlineWithContext(ctx context.Context) (string, error) { dst, err := GetWin32Proc(p.Pid) if err != nil { return "", fmt.Errorf("could not get CommandLine: %s", err) @@ -174,6 +198,10 @@ func (p *Process) Cmdline() (string, error) { // element being an argument. This merely returns the CommandLine informations passed // to the process split on the 0x20 ASCII character. func (p *Process) CmdlineSlice() ([]string, error) { + return p.CmdlineSliceWithContext(context.Background()) +} + +func (p *Process) CmdlineSliceWithContext(ctx context.Context) ([]string, error) { cmdline, err := p.Cmdline() if err != nil { return nil, err @@ -182,6 +210,10 @@ func (p *Process) CmdlineSlice() ([]string, error) { } func (p *Process) CreateTime() (int64, error) { + return p.CreateTimeWithContext(context.Background()) +} + +func (p *Process) CreateTimeWithContext(ctx context.Context) (int64, error) { ru, err := getRusage(p.Pid) if err != nil { return 0, fmt.Errorf("could not get CreationDate: %s", err) @@ -191,9 +223,17 @@ func (p *Process) CreateTime() (int64, error) { } func (p *Process) Cwd() (string, error) { + return p.CwdWithContext(context.Background()) +} + +func (p *Process) CwdWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Parent() (*Process, error) { + return p.ParentWithContext(context.Background()) +} + +func (p *Process) ParentWithContext(ctx context.Context) (*Process, error) { dst, err := GetWin32Proc(p.Pid) if err != nil { return nil, fmt.Errorf("could not get ParentProcessID: %s", err) @@ -202,9 +242,17 @@ func (p *Process) Parent() (*Process, error) { return NewProcess(int32(dst[0].ParentProcessID)) } func (p *Process) Status() (string, error) { + return p.StatusWithContext(context.Background()) +} + +func (p *Process) StatusWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } func (p *Process) Username() (string, error) { + return p.UsernameWithContext(context.Background()) +} + +func (p *Process) UsernameWithContext(ctx context.Context) (string, error) { pid := p.Pid // 0x1000 is PROCESS_QUERY_LIMITED_INFORMATION c, err := syscall.OpenProcess(0x1000, false, uint32(pid)) @@ -226,20 +274,36 @@ func (p *Process) Username() (string, error) { } func (p *Process) Uids() ([]int32, error) { + return p.UidsWithContext(context.Background()) +} + +func (p *Process) UidsWithContext(ctx context.Context) ([]int32, error) { var uids []int32 return uids, common.ErrNotImplementedError } func (p *Process) Gids() ([]int32, error) { + return p.GidsWithContext(context.Background()) +} + +func (p *Process) GidsWithContext(ctx context.Context) ([]int32, error) { var gids []int32 return gids, common.ErrNotImplementedError } func (p *Process) Terminal() (string, error) { + return p.TerminalWithContext(context.Background()) +} + +func (p *Process) TerminalWithContext(ctx context.Context) (string, error) { return "", common.ErrNotImplementedError } // Nice returnes priority in Windows func (p *Process) Nice() (int32, error) { + return p.NiceWithContext(context.Background()) +} + +func (p *Process) NiceWithContext(ctx context.Context) (int32, error) { dst, err := GetWin32Proc(p.Pid) if err != nil { return 0, fmt.Errorf("could not get Priority: %s", err) @@ -247,20 +311,36 @@ func (p *Process) Nice() (int32, error) { return int32(dst[0].Priority), nil } func (p *Process) IOnice() (int32, error) { + return p.IOniceWithContext(context.Background()) +} + +func (p *Process) IOniceWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) Rlimit() ([]RlimitStat, error) { + return p.RlimitWithContext(context.Background()) +} + +func (p *Process) RlimitWithContext(ctx context.Context) ([]RlimitStat, error) { var rlimit []RlimitStat return rlimit, common.ErrNotImplementedError } -func (p *Process) RlimitUsage(_ bool) ([]RlimitStat, error) { +func (p *Process) RlimitUsage(gatherUsed bool) ([]RlimitStat, error) { + return p.RlimitUsageWithContext(context.Background(), gatherUsed) +} + +func (p *Process) RlimitUsageWithContext(ctx context.Context, gatherUsed bool) ([]RlimitStat, error) { var rlimit []RlimitStat return rlimit, common.ErrNotImplementedError } func (p *Process) IOCounters() (*IOCountersStat, error) { + return p.IOCountersWithContext(context.Background()) +} + +func (p *Process) IOCountersWithContext(ctx context.Context) (*IOCountersStat, error) { dst, err := GetWin32Proc(p.Pid) if err != nil || len(dst) == 0 { return nil, fmt.Errorf("could not get Win32Proc: %s", err) @@ -275,12 +355,24 @@ func (p *Process) IOCounters() (*IOCountersStat, error) { return ret, nil } func (p *Process) NumCtxSwitches() (*NumCtxSwitchesStat, error) { + return p.NumCtxSwitchesWithContext(context.Background()) +} + +func (p *Process) NumCtxSwitchesWithContext(ctx context.Context) (*NumCtxSwitchesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NumFDs() (int32, error) { + return p.NumFDsWithContext(context.Background()) +} + +func (p *Process) NumFDsWithContext(ctx context.Context) (int32, error) { return 0, common.ErrNotImplementedError } func (p *Process) NumThreads() (int32, error) { + return p.NumThreadsWithContext(context.Background()) +} + +func (p *Process) NumThreadsWithContext(ctx context.Context) (int32, error) { dst, err := GetWin32Proc(p.Pid) if err != nil { return 0, fmt.Errorf("could not get ThreadCount: %s", err) @@ -288,10 +380,18 @@ func (p *Process) NumThreads() (int32, error) { return int32(dst[0].ThreadCount), nil } func (p *Process) Threads() (map[int32]*cpu.TimesStat, error) { + return p.ThreadsWithContext(context.Background()) +} + +func (p *Process) ThreadsWithContext(ctx context.Context) (map[int32]*cpu.TimesStat, error) { ret := make(map[int32]*cpu.TimesStat) return ret, common.ErrNotImplementedError } func (p *Process) Times() (*cpu.TimesStat, error) { + return p.TimesWithContext(context.Background()) +} + +func (p *Process) TimesWithContext(ctx context.Context) (*cpu.TimesStat, error) { sysTimes, err := getProcessCPUTimes(p.Pid) if err != nil { return nil, err @@ -315,9 +415,17 @@ func (p *Process) Times() (*cpu.TimesStat, error) { }, nil } func (p *Process) CPUAffinity() ([]int32, error) { + return p.CPUAffinityWithContext(context.Background()) +} + +func (p *Process) CPUAffinityWithContext(ctx context.Context) ([]int32, error) { return nil, common.ErrNotImplementedError } func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { + return p.MemoryInfoWithContext(context.Background()) +} + +func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, error) { mem, err := getMemoryInfo(p.Pid) if err != nil { return nil, err @@ -331,10 +439,18 @@ func (p *Process) MemoryInfo() (*MemoryInfoStat, error) { return ret, nil } func (p *Process) MemoryInfoEx() (*MemoryInfoExStat, error) { + return p.MemoryInfoExWithContext(context.Background()) +} + +func (p *Process) MemoryInfoExWithContext(ctx context.Context) (*MemoryInfoExStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Children() ([]*Process, error) { + return p.ChildrenWithContext(context.Background()) +} + +func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) { var dst []Win32_Process query := wmi.CreateQuery(&dst, fmt.Sprintf("Where ParentProcessId = %d", p.Pid)) ctx, cancel := context.WithTimeout(context.Background(), common.Timeout) @@ -357,22 +473,42 @@ func (p *Process) Children() ([]*Process, error) { } func (p *Process) OpenFiles() ([]OpenFilesStat, error) { + return p.OpenFilesWithContext(context.Background()) +} + +func (p *Process) OpenFilesWithContext(ctx context.Context) ([]OpenFilesStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) Connections() ([]net.ConnectionStat, error) { + return p.ConnectionsWithContext(context.Background()) +} + +func (p *Process) ConnectionsWithContext(ctx context.Context) ([]net.ConnectionStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) NetIOCounters(pernic bool) ([]net.IOCountersStat, error) { + return p.NetIOCountersWithContext(context.Background(), pernic) +} + +func (p *Process) NetIOCountersWithContext(ctx context.Context, pernic bool) ([]net.IOCountersStat, error) { return nil, common.ErrNotImplementedError } func (p *Process) IsRunning() (bool, error) { + return p.IsRunningWithContext(context.Background()) +} + +func (p *Process) IsRunningWithContext(ctx context.Context) (bool, error) { return true, common.ErrNotImplementedError } func (p *Process) MemoryMaps(grouped bool) (*[]MemoryMapsStat, error) { + return p.MemoryMapsWithContext(context.Background(), grouped) +} + +func (p *Process) MemoryMapsWithContext(ctx context.Context, grouped bool) (*[]MemoryMapsStat, error) { var ret []MemoryMapsStat return &ret, common.ErrNotImplementedError } @@ -384,17 +520,33 @@ func NewProcess(pid int32) (*Process, error) { } func (p *Process) SendSignal(sig windows.Signal) error { + return p.SendSignalWithContext(context.Background(), sig) +} + +func (p *Process) SendSignalWithContext(ctx context.Context, sig windows.Signal) error { return common.ErrNotImplementedError } func (p *Process) Suspend() error { + return p.SuspendWithContext(context.Background()) +} + +func (p *Process) SuspendWithContext(ctx context.Context) error { return common.ErrNotImplementedError } func (p *Process) Resume() error { + return p.ResumeWithContext(context.Background()) +} + +func (p *Process) ResumeWithContext(ctx context.Context) error { return common.ErrNotImplementedError } func (p *Process) Terminate() error { + return p.TerminateWithContext(context.Background()) +} + +func (p *Process) TerminateWithContext(ctx context.Context) error { // PROCESS_TERMINATE = 0x0001 proc := w32.OpenProcess(0x0001, false, uint32(p.Pid)) ret := w32.TerminateProcess(proc, 0) @@ -408,6 +560,10 @@ func (p *Process) Terminate() error { } func (p *Process) Kill() error { + return p.KillWithContext(context.Background()) +} + +func (p *Process) KillWithContext(ctx context.Context) error { process := os.Process{Pid: int(p.Pid)} return process.Kill() } From e776f6384a7fa7bb3aad41bb9afdffb02bcdfb31 Mon Sep 17 00:00:00 2001 From: shirou Date: Tue, 9 Jan 2018 11:44:33 +0900 Subject: [PATCH 2/2] [docker]: fix typo. --- docker/docker_linux.go | 1 - 1 file changed, 1 deletion(-) diff --git a/docker/docker_linux.go b/docker/docker_linux.go index c0724db..ef6cae0 100644 --- a/docker/docker_linux.go +++ b/docker/docker_linux.go @@ -4,7 +4,6 @@ package docker import ( "context" - "encoding/json" "fmt" "os" "os/exec"