Skip to content
This repository has been archived by the owner on Nov 14, 2023. It is now read-only.

Add process collector #24

Merged
merged 5 commits into from
Mar 29, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions processes/gops/process_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

type ProcessInfo struct {
PID int32
PPID int32
Name string
RSS uint64
PctMem float64
Expand Down Expand Up @@ -50,6 +51,9 @@ func GetProcesses() ([]*ProcessInfo, error) {
processInfos = append(processInfos, processInfo)
}

// platform-specific post-processing on the collected info
postProcess(processInfos)

return processInfos, nil
}

Expand All @@ -60,7 +64,12 @@ func newProcessInfo(p *process.Process, pid int32, totalMem float64) (*ProcessIn
return nil, err
}

name, err := pickName(p)
ppid, err := p.Ppid()
if err != nil {
return nil, err
}

name, err := p.Name()
if err != nil {
return nil, err
}
Expand All @@ -72,5 +81,5 @@ func newProcessInfo(p *process.Process, pid int32, totalMem float64) (*ProcessIn
return nil, err
}

return &ProcessInfo{pid, name, memInfo.RSS, pctMem, memInfo.VMS, username}, nil
return &ProcessInfo{pid, ppid, name, memInfo.RSS, pctMem, memInfo.VMS, username}, nil
}
9 changes: 2 additions & 7 deletions processes/gops/process_info_darwin.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
package gops

import (
"github.com/shirou/gopsutil/process"
)

func pickName(p *process.Process) (string, error) {
return p.Name()
}
// Do nothing for now
func postProcess(processInfos []*ProcessInfo) {}
38 changes: 29 additions & 9 deletions processes/gops/process_info_linux.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,40 @@
package gops

import (
"strings"
"fmt"

"github.com/shirou/gopsutil/process"
)

func pickName(p *process.Process) (string, error) {
cmdline, err := p.Cmdline()
if err != nil {
return "", err
// Build a hash pid -> ppid
func buildPIDHash(processInfos []*ProcessInfo) (hash map[int32]int32) {
hash = make(map[int32]int32)
for _, processInfo := range processInfos {
hash[processInfo.PID] = processInfo.PPID
}
// Assume that the process is a kernel process when it has no args
if strings.TrimSpace(cmdline) == "" {
return "kernel", nil
return
}

// Return whether the PID is of a kernel thread, based on whether it has
// the init process (PID 1) as ancestor
func isKernelThread(pid int32, pidHash map[int32]int32) bool {
if pid == 1 {
return false
}
ppid, ok := pidHash[pid]
if !ok {
return true
}

return p.Name()
return isKernelThread(ppid, pidHash)
}

// Name processes "kernel" if they're a kernel thread
func postProcess(processInfos []*ProcessInfo) {
pidHash := buildPIDHash(processInfos)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the processInfo's are not precisely a snapshot of the process table due to the fact that while we iterate the table to get the info - this table might change, I'm therefore (quite mildly) concerned that it could leave a slightly tainted table that wouldn't always lead to 1 or what would be worse some weird loop.

We could maybe add a maximum depth isKernelThread might go before deciding it's NOT a kernel thread. In general kernel threads would have a depth of 2 maximum. I'm sure if we go 4 or 5 levels into the recursion we can be certain it's not a kernel thread.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, hadn't thought about that.

Addressed this by adding a recursion limit, let me know what you think.

for _, processInfo := range processInfos {
if isKernelThread(processInfo.PID, pidHash) {
processInfo.Name = "kernel"
}
}
}