Skip to content

Commit

Permalink
cgroups: kill processes when deleting a cgroup
Browse files Browse the repository at this point in the history
if the cgroup cleanup fails with EBUSY, attempt to kill the
processes.

Related to: containers/podman#14057

Signed-off-by: Giuseppe Scrivano <[email protected]>
  • Loading branch information
giuseppe committed May 3, 2022
1 parent 8c809a0 commit 0d91c25
Showing 1 changed file with 22 additions and 2 deletions.
24 changes: 22 additions & 2 deletions pkg/cgroups/cgroups_supported.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
"sync"
"syscall"
Expand Down Expand Up @@ -96,6 +97,17 @@ func UserOwnsCurrentSystemdCgroup() (bool, error) {
// It differs from os.RemoveAll as it doesn't attempt to unlink files.
// On cgroupfs we are allowed only to rmdir empty directories.
func rmDirRecursively(path string) error {
killProcesses := func(signal syscall.Signal) {
// kill all the processes that are still part of the cgroup
if procs, err := ioutil.ReadFile(filepath.Join(path, "cgroup.procs")); err == nil {
for _, pidS := range strings.Split(string(procs), "\n") {
if pid, err := strconv.Atoi(pidS); err == nil {
_ = unix.Kill(pid, signal)
}
}
}
}

if err := os.Remove(path); err == nil || os.IsNotExist(err) {
return nil
}
Expand All @@ -118,8 +130,16 @@ func rmDirRecursively(path string) error {
return nil
}
if errors.Is(err, unix.EBUSY) {
// attempt up to 5 seconds if the cgroup is busy
if attempts < 500 {
// send a SIGTERM after 3 second
if attempts == 300 {
killProcesses(unix.SIGTERM)
}
// send SIGKILL after 8 seconds
if attempts == 800 {
killProcesses(unix.SIGKILL)
}
// give up after 10 seconds
if attempts < 1000 {
time.Sleep(time.Millisecond * 10)
attempts++
continue
Expand Down

0 comments on commit 0d91c25

Please sign in to comment.