Skip to content

Commit 8e9e14c

Browse files
committed
cgroup delete: proceed to the next subsystem when a cgroup is not found
The Delete method checks for running processes within each subsystem, before deleting the cgroup from it. On certain systems, there are cases when removing a cgroup from one subsystem, also removes it from others. For example, removing a cgroup from net_cls subsystem also removes the cgroup from net_prio. This is because both net_cls and net_prio have a symlink to 'net_cls,net_prio'. This is also true for cpu and cpuacct. This change handles the above case, when a query to get cgroup processes within a subsystem returns a fs.ErrNotExist. In such a case, we move to the next subsystem, instead of erroring out of Delete() immediately. This ensures that the cgroup is deleted from all subsystems that have it. Signed-off-by: Anuj Singh <[email protected]>
1 parent f4638b4 commit 8e9e14c

3 files changed

Lines changed: 29 additions & 0 deletions

File tree

cgroup1/cgroup.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ func (c *cgroup) Delete() error {
259259
// kernel prevents cgroups with running process from being removed, check the tree is empty
260260
procs, err := c.processes(s.Name(), true, cgroupProcs)
261261
if err != nil {
262+
// if the control group does not exist within a subsystem, then proceed to the next subsystem
263+
if errors.Is(err, os.ErrNotExist) {
264+
continue
265+
}
262266
return err
263267
}
264268
if len(procs) > 0 {

cgroup1/cgroup_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,13 @@ func TestDelete(t *testing.T) {
459459
t.Error(err)
460460
return
461461
}
462+
463+
err = mock.symLink()
464+
if err != nil {
465+
t.Error(err)
466+
return
467+
}
468+
462469
if err := control.Delete(); err != nil {
463470
t.Error(err)
464471
}

cgroup1/mock_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,21 @@ func (m *mockCgroup) delete() error {
7373
func (m *mockCgroup) hierarchy() ([]Subsystem, error) {
7474
return m.subsystems, nil
7575
}
76+
77+
// symLink() creates a symlink between net_cls and net_prio for testing
78+
// On certain Linux systems, there's a symlink from both net_cls and net_prio to "net_cls,net_prio"
79+
// Since we don't have a subsystem defined for "net_cls,net_prio",
80+
// we mock this behavior by creating a symlink directly between net_cls and net_prio
81+
func (m *mockCgroup) symLink() error {
82+
netCLS := filepath.Join(m.root, string(NetCLS))
83+
netPrio := filepath.Join(m.root, string(NetPrio))
84+
// remove netCLS before creating a symlink
85+
if err := os.RemoveAll(netCLS); err != nil {
86+
return err
87+
}
88+
// create symlink between net_cls and net_prio
89+
if err := os.Symlink(netPrio, netCLS); err != nil {
90+
return err
91+
}
92+
return nil
93+
}

0 commit comments

Comments
 (0)