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 6c02139
Showing 1 changed file with 27 additions and 2 deletions.
29 changes: 27 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,22 @@ 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) {
if signal == unix.SIGKILL {
if err := ioutil.WriteFile(filepath.Join(path, "cgroup.kill"), []byte("1"), 0600); err == nil {
return
}
}
// 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 +135,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 6c02139

Please sign in to comment.