1
0
mirror of https://github.com/shirou/gopsutil.git synced 2025-04-24 13:48:56 +08:00

Merge pull request #1706 from Lomanic/issue1698

[process][darwin][freebsd][linux][openbsd] Make process.Children not reliant on pgrep
This commit is contained in:
shirou 2024-09-11 22:28:07 +09:00 committed by GitHub
commit e89f21d7dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 57 additions and 51 deletions

View File

@ -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
}

View File

@ -18,7 +18,7 @@ import (
var (
invoke common.Invoker = common.Invoke{}
ErrorNoChildren = errors.New("process does not have children")
ErrorNoChildren = errors.New("process does not have children") // Deprecated: ErrorNoChildren is never returned by process.Children(), check its returned []*Process slice length instead
ErrorProcessNotRunning = errors.New("process does not exist")
ErrorNotPermitted = errors.New("operation not permitted")
)

View File

@ -7,6 +7,7 @@ import (
"context"
"fmt"
"path/filepath"
"sort"
"strconv"
"strings"
@ -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
}

View File

@ -8,6 +8,7 @@ import (
"context"
"errors"
"path/filepath"
"sort"
"strconv"
"strings"
@ -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
}

View File

@ -12,6 +12,7 @@ import (
"math"
"os"
"path/filepath"
"sort"
"strconv"
"strings"
@ -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
}

View File

@ -11,6 +11,7 @@ import (
"fmt"
"io"
"path/filepath"
"sort"
"strconv"
"strings"
"unsafe"
@ -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
}