cgroups: kill processes when deleting a cgroup
if the cgroup cleanup fails with EBUSY, attempt to kill the processes. Related to: https://github.com/containers/podman/issues/14057 Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
parent
d8a414a535
commit
987031a01e
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
@ -96,6 +97,22 @@ func UserOwnsCurrentSystemdCgroup() (bool, error) {
|
||||||
// It differs from os.RemoveAll as it doesn't attempt to unlink files.
|
// It differs from os.RemoveAll as it doesn't attempt to unlink files.
|
||||||
// On cgroupfs we are allowed only to rmdir empty directories.
|
// On cgroupfs we are allowed only to rmdir empty directories.
|
||||||
func rmDirRecursively(path string) error {
|
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) {
|
if err := os.Remove(path); err == nil || os.IsNotExist(err) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -118,8 +135,16 @@ func rmDirRecursively(path string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if errors.Is(err, unix.EBUSY) {
|
if errors.Is(err, unix.EBUSY) {
|
||||||
// attempt up to 5 seconds if the cgroup is busy
|
// send a SIGTERM after 3 second
|
||||||
if attempts < 500 {
|
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)
|
time.Sleep(time.Millisecond * 10)
|
||||||
attempts++
|
attempts++
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue