Skip to content

Commit

Permalink
[process][darwin][freebsd][linux][openbsd] Make process.Children not …
Browse files Browse the repository at this point in the history
…reliant on pgrep

pgrep -P $PID exits with status of 1 (and nothing in stdout nor stderr) both if
a process doesn't exist or it doesn't have child processes, so we don't
use it anymore on these OSes.

Also remove the ErrorNoChildren error when there are no child processes,
this is erroneous (simply check for the length of the returned slice, plus
this is not an error per se), this was only returned on linux anyway.

Fixes shirou#1698
  • Loading branch information
Lomanic committed Sep 7, 2024
1 parent 74cb403 commit 9eed743
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 51 deletions.
20 changes: 0 additions & 20 deletions internal/common/common_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,23 +40,3 @@ func CallLsofWithContext(ctx context.Context, invoke Invoker, pid int32, args ..
}
return ret, nil
}

func CallPgrepWithContext(ctx context.Context, invoke Invoker, pid int32) ([]int32, error) {
out, err := invoke.CommandWithContext(ctx, "pgrep", "-P", strconv.Itoa(int(pid)))
if err != nil {
return []int32{}, err
}
lines := strings.Split(string(out), "\n")
ret := make([]int32, 0, len(lines))
for _, l := range lines {
if len(l) == 0 {
continue
}
i, err := strconv.ParseInt(l, 10, 32)
if err != nil {
continue
}
ret = append(ret, int32(i))
}
return ret, nil
}
1 change: 0 additions & 1 deletion process/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (

var (
invoke common.Invoker = common.Invoke{}
ErrorNoChildren = errors.New("process does not have children")
ErrorProcessNotRunning = errors.New("process does not exist")
ErrorNotPermitted = errors.New("operation not permitted")
)
Expand Down
16 changes: 9 additions & 7 deletions process/process_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,17 +233,19 @@ func convertCPUTimes(s string) (ret float64, err error) {
}

func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
pids, err := common.CallPgrepWithContext(ctx, invoke, p.Pid)
procs, err := ProcessesWithContext(ctx)
if err != nil {
return nil, err
return nil, nil
}
ret := make([]*Process, 0, len(pids))
for _, pid := range pids {
np, err := NewProcessWithContext(ctx, pid)
ret := make([]*Process, 0, len(procs))
for _, proc := range procs {
ppid, err := proc.PpidWithContext(ctx)
if err != nil {
return nil, err
continue
}
if ppid == p.Pid {
ret = append(ret, proc)
}
ret = append(ret, np)
}
return ret, nil
}
Expand Down
16 changes: 9 additions & 7 deletions process/process_freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,17 +269,19 @@ func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, e
}

func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
pids, err := common.CallPgrepWithContext(ctx, invoke, p.Pid)
procs, err := ProcessesWithContext(ctx)
if err != nil {
return nil, err
return nil, nil
}
ret := make([]*Process, 0, len(pids))
for _, pid := range pids {
np, err := NewProcessWithContext(ctx, pid)
ret := make([]*Process, 0, len(procs))
for _, proc := range procs {
ppid, err := proc.PpidWithContext(ctx)
if err != nil {
return nil, err
continue
}
if ppid == p.Pid {
ret = append(ret, proc)
}
ret = append(ret, np)
}
return ret, nil
}
Expand Down
32 changes: 23 additions & 9 deletions process/process_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"math"
"os"
"path/filepath"
"sort"
"strconv"
"strings"

Expand Down Expand Up @@ -338,21 +339,34 @@ func (p *Process) PageFaultsWithContext(ctx context.Context) (*PageFaultsStat, e
}

func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
pids, err := common.CallPgrepWithContext(ctx, invoke, p.Pid)
statFiles, err := filepath.Glob(common.HostProcWithContext(ctx, "[0-9]*/stat"))
if err != nil {
return nil, err
}
if len(pids) == 0 {
return nil, ErrorNoChildren
}
ret := make([]*Process, 0, len(pids))
for _, pid := range pids {
np, err := NewProcessWithContext(ctx, pid)
ret := make([]*Process, 0, len(statFiles))
for _, statFile := range statFiles {
statContents, err := os.ReadFile(statFile)
if err != nil {
return nil, err
continue
}
fields := splitProcStat(statContents)
pid, err := strconv.ParseInt(fields[1], 10, 32)
if err != nil {
continue
}
ppid, err := strconv.ParseInt(fields[4], 10, 32)
if err != nil {
continue
}
if int32(ppid) == p.Pid {
np, err := NewProcessWithContext(ctx, int32(pid))
if err != nil {
continue
}
ret = append(ret, np)
}
ret = append(ret, np)
}
sort.Slice(ret, func(i, j int) bool { return ret[i].Pid < ret[j].Pid })
return ret, nil
}

Expand Down
16 changes: 9 additions & 7 deletions process/process_openbsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,17 +286,19 @@ func (p *Process) MemoryInfoWithContext(ctx context.Context) (*MemoryInfoStat, e
}

func (p *Process) ChildrenWithContext(ctx context.Context) ([]*Process, error) {
pids, err := common.CallPgrepWithContext(ctx, invoke, p.Pid)
procs, err := ProcessesWithContext(ctx)
if err != nil {
return nil, err
return nil, nil
}
ret := make([]*Process, 0, len(pids))
for _, pid := range pids {
np, err := NewProcessWithContext(ctx, pid)
ret := make([]*Process, 0, len(procs))
for _, proc := range procs {
ppid, err := proc.PpidWithContext(ctx)
if err != nil {
return nil, err
continue
}
if ppid == p.Pid {
ret = append(ret, proc)
}
ret = append(ret, np)
}
return ret, nil
}
Expand Down

0 comments on commit 9eed743

Please sign in to comment.