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. We sort PIDs as pgrep did.

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 e5dddc6
Show file tree
Hide file tree
Showing 6 changed files with 56 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
18 changes: 11 additions & 7 deletions process/process_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"context"
"fmt"
"path/filepath"
"sort"
"strconv"
"strings"

Expand Down Expand Up @@ -233,18 +234,21 @@ 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)
}
sort.Slice(ret, func(i, j int) bool { return ret[i].Pid < ret[j].Pid })
return ret, nil
}

Expand Down
18 changes: 11 additions & 7 deletions process/process_freebsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"context"
"errors"
"path/filepath"
"sort"
"strconv"
"strings"

Expand Down Expand Up @@ -269,18 +270,21 @@ 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)
}
sort.Slice(ret, func(i, j int) bool { return ret[i].Pid < ret[j].Pid })
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
18 changes: 11 additions & 7 deletions process/process_openbsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"fmt"
"io"
"path/filepath"
"sort"
"strconv"
"strings"
"unsafe"
Expand Down Expand Up @@ -286,18 +287,21 @@ 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)
}
sort.Slice(ret, func(i, j int) bool { return ret[i].Pid < ret[j].Pid })
return ret, nil
}

Expand Down

0 comments on commit e5dddc6

Please sign in to comment.