...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package util
17
18 import (
19 "fmt"
20 "io"
21 "os"
22 "strconv"
23 "sync"
24
25 "github.com/go-logr/logr"
26 "github.com/pkg/errors"
27
28 "github.com/chaos-mesh/chaos-mesh/pkg/bpm"
29 "github.com/chaos-mesh/chaos-mesh/pkg/chaosdaemon/graph"
30 )
31
32
33 func ReadCommName(pid int) (string, error) {
34 f, err := os.Open(fmt.Sprintf("%s/%d/comm", bpm.DefaultProcPrefix, pid))
35 if err != nil {
36 return "", err
37 }
38 defer f.Close()
39
40 b, err := io.ReadAll(f)
41 if err != nil {
42 return "", err
43 }
44
45 return string(b), nil
46 }
47
48
49
50 func GetChildProcesses(ppid uint32, logger logr.Logger) ([]uint32, error) {
51 procs, err := os.ReadDir(bpm.DefaultProcPrefix)
52 if err != nil {
53 return nil, errors.Wrapf(err, "read /proc")
54 }
55
56 type processPair struct {
57 Pid uint32
58 Ppid uint32
59 }
60
61 pairs := make(chan processPair)
62 done := make(chan bool)
63
64 go func() {
65 var wg sync.WaitGroup
66
67 for _, proc := range procs {
68 _, err := strconv.ParseUint(proc.Name(), 10, 32)
69 if err != nil {
70 continue
71 }
72
73 statusPath := bpm.DefaultProcPrefix + "/" + proc.Name() + "/stat"
74
75 wg.Add(1)
76 go func() {
77 defer wg.Done()
78
79 reader, err := os.Open(statusPath)
80 if err != nil {
81 logger.Error(err, "read status file error", "path", statusPath)
82 return
83 }
84 defer reader.Close()
85
86 var (
87 pid uint32
88 comm string
89 state string
90 parent uint32
91 )
92
93 fmt.Fscanf(reader, "%d %s %s %d", &pid, &comm, &state, &parent)
94
95 pairs <- processPair{
96 Pid: pid,
97 Ppid: parent,
98 }
99 }()
100 }
101
102 wg.Wait()
103 done <- true
104 }()
105
106 processGraph := graph.NewGraph()
107 for {
108 select {
109 case pair := <-pairs:
110 processGraph.Insert(pair.Ppid, pair.Pid)
111 case <-done:
112 return processGraph.Flatten(ppid, logger), nil
113 }
114 }
115 }
116
117 func EncodeOutputToError(output []byte, err error) error {
118 return errors.Errorf("error code: %v, msg: %s", err, string(output))
119 }
120