Skip to content
This repository was archived by the owner on Jul 22, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
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
7 changes: 6 additions & 1 deletion process.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ type Process interface {
// process table, in which case the process table returned might contain
// ephemeral entities that happened to be running when this was called.
func Processes() ([]Process, error) {
return processes()
return processes(nil)
}

// FilterProcesses returns processes that satisfy the predicate f.
func FilterProcesses(f func(Process) bool) ([]Process, error) {
return processes(f)
}

// FindProcess looks up a single process by pid.
Expand Down
43 changes: 24 additions & 19 deletions process_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,49 +28,54 @@ func (p *DarwinProcess) Executable() string {
}

func findProcess(pid int) (Process, error) {
ps, err := processes()
f := func(p Process) bool {
if p.Pid() == pid {
return true
}
return false
}
ps, err := FilterProcesses(f)

if err != nil {
return nil, err
}

for _, p := range ps {
if p.Pid() == pid {
return p, nil
}
if len(ps) == 0 {
return nil, nil
}

return nil, nil
return ps[0], nil
}

func processes() ([]Process, error) {
func processes(f func(Process) bool) ([]Process, error) {
buf, err := darwinSyscall()
if err != nil {
return nil, err
}

procs := make([]*kinfoProc, 0, 50)
procs := make([]Process, 0, 50)
proc := &kinfoProc{}
k := 0
for i := _KINFO_STRUCT_SIZE; i < buf.Len(); i += _KINFO_STRUCT_SIZE {
proc := &kinfoProc{}
err = binary.Read(bytes.NewBuffer(buf.Bytes()[k:i]), binary.LittleEndian, proc)
if err != nil {
return nil, err
}

k = i
procs = append(procs, proc)
}

darwinProcs := make([]Process, len(procs))
for i, p := range procs {
darwinProcs[i] = &DarwinProcess{
pid: int(p.Pid),
ppid: int(p.PPid),
binary: darwinCstring(p.Comm),
dp := &DarwinProcess{
pid: int(proc.Pid),
ppid: int(proc.PPid),
binary: darwinCstring(proc.Comm),
}
if f != nil && !f(dp) {
continue
}

procs = append(procs, dp)
}

return darwinProcs, nil
return procs, nil
}

func darwinCstring(s [16]byte) string {
Expand Down
5 changes: 4 additions & 1 deletion process_freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ func findProcess(pid int) (Process, error) {
return newUnixProcess(pid)
}

func processes() ([]Process, error) {
func processes(f func(Process) bool) ([]Process, error) {
results := make([]Process, 0, 50)

mib := []int32{CTL_KERN, KERN_PROC, KERN_PROC_PROC, 0}
Expand All @@ -198,6 +198,9 @@ func processes() ([]Process, error) {
continue
}
p.ppid, p.pgrp, p.sid, p.binary = copy_params(&k)
if f != nil && !f(p) {
continue
}

results = append(results, p)
}
Expand Down
32 changes: 32 additions & 0 deletions process_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ps

import (
"os"
"os/exec"
"testing"
)

Expand Down Expand Up @@ -43,3 +44,34 @@ func TestProcesses(t *testing.T) {
t.Fatal("should have Go")
}
}

func TestFilterProcesses(t *testing.T) {
// should have go
cmd := exec.Command("go")
err := cmd.Start()
if err != nil {
t.Fatalf("err: %s", err)
}
// Return true only if p is the process started by cmd.Start()
f := func(p Process) bool {
pid := os.Getpid()
if p.PPid() == pid {
return true
}
return false
}
p, err := FilterProcesses(f)
_ = cmd.Wait()
if err != nil {
t.Fatalf("err: %s", err)
}

if len(p) != 1 {
t.Fatal("should have one go processe")
}

if p[0].Executable() != "go" && p[0].Executable() != "go.exe" {
t.Fatal("should have one go processe")
}

}
6 changes: 5 additions & 1 deletion process_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func findProcess(pid int) (Process, error) {
return newUnixProcess(pid)
}

func processes() ([]Process, error) {
func processes(f func(Process) bool) ([]Process, error) {
d, err := os.Open("/proc")
if err != nil {
return nil, err
Expand Down Expand Up @@ -116,6 +116,10 @@ func processes() ([]Process, error) {
continue
}

if f != nil && !f(p) {
continue
}

results = append(results, p)
}
}
Expand Down
24 changes: 16 additions & 8 deletions process_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,21 +75,26 @@ func newWindowsProcess(e *PROCESSENTRY32) *WindowsProcess {
}

func findProcess(pid int) (Process, error) {
ps, err := processes()
f := func(p Process) bool {
if p.Pid() == pid {
return true
}
return false
}
ps, err := FilterProcesses(f)

if err != nil {
return nil, err
}

for _, p := range ps {
if p.Pid() == pid {
return p, nil
}
if len(ps) == 0 {
return nil, nil
}

return nil, nil
return ps[0], nil
}

func processes() ([]Process, error) {
func processes(f func(Process) bool) ([]Process, error) {
handle, _, _ := procCreateToolhelp32Snapshot.Call(
0x00000002,
0)
Expand All @@ -107,7 +112,10 @@ func processes() ([]Process, error) {

results := make([]Process, 0, 50)
for {
results = append(results, newWindowsProcess(&entry))
p := newWindowsProcess(&entry)
if f == nil || f(p) {
results = append(results, p)
}

ret, _, _ := procProcess32Next.Call(handle, uintptr(unsafe.Pointer(&entry)))
if ret == 0 {
Expand Down