Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit a31a0ff

Browse files
committed
Add functionality for retrieving all tasks of a cgroup
Signed-off-by: Georgia Panoutsakopoulou <[email protected]>
1 parent 82cb49f commit a31a0ff

File tree

4 files changed

+117
-1
lines changed

4 files changed

+117
-1
lines changed

cgroup.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,49 @@ func (c *cgroup) processes(subsystem Name, recursive bool) ([]Process, error) {
321321
return processes, err
322322
}
323323

324+
// Tasks returns the tasks running inside the cgroup along
325+
// with the subsystem used, pid, and path
326+
func (c *cgroup) Tasks(subsystem Name, recursive bool) ([]Task, error) {
327+
c.mu.Lock()
328+
defer c.mu.Unlock()
329+
if c.err != nil {
330+
return nil, c.err
331+
}
332+
return c.tasks(subsystem, recursive)
333+
}
334+
335+
func (c *cgroup) tasks(subsystem Name, recursive bool) ([]Task, error) {
336+
s := c.getSubsystem(subsystem)
337+
sp, err := c.path(subsystem)
338+
if err != nil {
339+
return nil, err
340+
}
341+
path := s.(pather).Path(sp)
342+
var tasks []Task
343+
err = filepath.Walk(path, func(p string, info os.FileInfo, err error) error {
344+
if err != nil {
345+
return err
346+
}
347+
if !recursive && info.IsDir() {
348+
if p == path {
349+
return nil
350+
}
351+
return filepath.SkipDir
352+
}
353+
dir, name := filepath.Split(p)
354+
if name != cgroupTasks {
355+
return nil
356+
}
357+
procs, err := readTasksPids(dir, subsystem)
358+
if err != nil {
359+
return err
360+
}
361+
tasks = append(tasks, procs...)
362+
return nil
363+
})
364+
return tasks, err
365+
}
366+
324367
// Freeze freezes the entire cgroup and all the processes inside it
325368
func (c *cgroup) Freeze() error {
326369
c.mu.Lock()

cgroup_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,41 @@ func TestListPids(t *testing.T) {
159159
}
160160
}
161161

162+
func TestListTasksPids(t *testing.T) {
163+
mock, err := newMock()
164+
if err != nil {
165+
t.Fatal(err)
166+
}
167+
defer mock.delete()
168+
control, err := New(mock.hierarchy, StaticPath("test"), &specs.LinuxResources{})
169+
if err != nil {
170+
t.Error(err)
171+
return
172+
}
173+
if err := control.AddTask(Process{Pid: 1234}); err != nil {
174+
t.Error(err)
175+
return
176+
}
177+
for _, s := range Subsystems() {
178+
if err := checkTaskid(mock, filepath.Join(string(s), "test"), 1234); err != nil {
179+
t.Error(err)
180+
return
181+
}
182+
}
183+
tasks, err := control.Tasks(Freezer, false)
184+
if err != nil {
185+
t.Error(err)
186+
return
187+
}
188+
if l := len(tasks); l != 1 {
189+
t.Errorf("should have one task but received %d", l)
190+
return
191+
}
192+
if tasks[0].Pid != 1234 {
193+
t.Errorf("expected task pid %d but received %d", 1234, tasks[0].Pid)
194+
}
195+
}
196+
162197
func readValue(mock *mockCgroup, path string) (string, error) {
163198
data, err := ioutil.ReadFile(filepath.Join(mock.root, path))
164199
if err != nil {

control.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,15 @@ type Process struct {
4444
Path string
4545
}
4646

47+
type Task struct {
48+
// Subsystem is the name of the subsystem that the task is in
49+
Subsystem Name
50+
// Pid is the process id of the task
51+
Pid int
52+
// Path is the full path of the subsystem and location that the task is in
53+
Path string
54+
}
55+
4756
// Cgroup handles interactions with the individual groups to perform
4857
// actions on them as them main interface to this cgroup package
4958
type Cgroup interface {
@@ -64,6 +73,8 @@ type Cgroup interface {
6473
Update(resources *specs.LinuxResources) error
6574
// Processes returns all the processes in a select subsystem for the cgroup
6675
Processes(Name, bool) ([]Process, error)
76+
// Tasks returns all the tasks in a select subsystem for the cgroup
77+
Tasks(Name, bool) ([]Task, error)
6778
// Freeze freezes or pauses all processes inside the cgroup
6879
Freeze() error
6980
// Thaw thaw or resumes all processes inside the cgroup

utils.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ func remove(path string) error {
111111
return fmt.Errorf("cgroups: unable to remove path %q", path)
112112
}
113113

114-
// readPids will read all the pids in a cgroup by the provided path
114+
// readPids will read all the pids of processes in a cgroup by the provided path
115115
func readPids(path string, subsystem Name) ([]Process, error) {
116116
f, err := os.Open(filepath.Join(path, cgroupProcs))
117117
if err != nil {
@@ -138,6 +138,33 @@ func readPids(path string, subsystem Name) ([]Process, error) {
138138
return out, nil
139139
}
140140

141+
// readTasksPids will read all the pids of tasks in a cgroup by the provided path
142+
func readTasksPids(path string, subsystem Name) ([]Task, error) {
143+
f, err := os.Open(filepath.Join(path, cgroupTasks))
144+
if err != nil {
145+
return nil, err
146+
}
147+
defer f.Close()
148+
var (
149+
out []Task
150+
s = bufio.NewScanner(f)
151+
)
152+
for s.Scan() {
153+
if t := s.Text(); t != "" {
154+
pid, err := strconv.Atoi(t)
155+
if err != nil {
156+
return nil, err
157+
}
158+
out = append(out, Task{
159+
Pid: pid,
160+
Subsystem: subsystem,
161+
Path: path,
162+
})
163+
}
164+
}
165+
return out, nil
166+
}
167+
141168
func hugePageSizes() ([]string, error) {
142169
var (
143170
pageSizes []string

0 commit comments

Comments
 (0)