mirror of
https://github.com/containers/podman.git
synced 2025-06-26 12:56:45 +08:00
Merge pull request #3554 from giuseppe/fix-cgroupfs-cleanup
cgroups: fix a leak when using cgroupfs
This commit is contained in:
@ -37,7 +37,7 @@ func (c *blkioHandler) Create(ctr *CgroupControl) (bool, error) {
|
|||||||
|
|
||||||
// Destroy the cgroup
|
// Destroy the cgroup
|
||||||
func (c *blkioHandler) Destroy(ctr *CgroupControl) error {
|
func (c *blkioHandler) Destroy(ctr *CgroupControl) error {
|
||||||
return os.Remove(ctr.getCgroupv1Path(Blkio))
|
return rmDirRecursively(ctr.getCgroupv1Path(Blkio))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat fills a metrics structure with usage stats for the controller
|
// Stat fills a metrics structure with usage stats for the controller
|
||||||
|
@ -327,6 +327,13 @@ func Load(path string) (*CgroupControl, error) {
|
|||||||
path: path,
|
path: path,
|
||||||
systemd: false,
|
systemd: false,
|
||||||
}
|
}
|
||||||
|
if !cgroup2 {
|
||||||
|
controllers, err := getAvailableControllers(handlers, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
control.additionalControllers = controllers
|
||||||
|
}
|
||||||
if !cgroup2 {
|
if !cgroup2 {
|
||||||
for name := range handlers {
|
for name := range handlers {
|
||||||
p := control.getCgroupv1Path(name)
|
p := control.getCgroupv1Path(name)
|
||||||
@ -355,11 +362,40 @@ func (c *CgroupControl) Delete() error {
|
|||||||
return c.DeleteByPath(c.path)
|
return c.DeleteByPath(c.path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// rmDirRecursively delete recursively a cgroup directory.
|
||||||
|
// 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 {
|
||||||
|
if err := os.Remove(path); err == nil || os.IsNotExist(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
entries, err := ioutil.ReadDir(path)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrapf(err, "read %s", path)
|
||||||
|
}
|
||||||
|
for _, i := range entries {
|
||||||
|
if i.IsDir() {
|
||||||
|
if err := rmDirRecursively(filepath.Join(path, i.Name())); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if os.Remove(path); err != nil {
|
||||||
|
if !os.IsNotExist(err) {
|
||||||
|
return errors.Wrapf(err, "remove %s", path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteByPath deletes the specified cgroup path
|
// DeleteByPath deletes the specified cgroup path
|
||||||
func (c *CgroupControl) DeleteByPath(path string) error {
|
func (c *CgroupControl) DeleteByPath(path string) error {
|
||||||
if c.systemd {
|
if c.systemd {
|
||||||
return systemdDestroy(path)
|
return systemdDestroy(path)
|
||||||
}
|
}
|
||||||
|
if c.cgroup2 {
|
||||||
|
return rmDirRecursively(filepath.Join(cgroupRoot, c.path))
|
||||||
|
}
|
||||||
var lastError error
|
var lastError error
|
||||||
for _, h := range handlers {
|
for _, h := range handlers {
|
||||||
if err := h.Destroy(c); err != nil {
|
if err := h.Destroy(c); err != nil {
|
||||||
@ -368,8 +404,11 @@ func (c *CgroupControl) DeleteByPath(path string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, ctr := range c.additionalControllers {
|
for _, ctr := range c.additionalControllers {
|
||||||
|
if ctr.symlink {
|
||||||
|
continue
|
||||||
|
}
|
||||||
p := c.getCgroupv1Path(ctr.name)
|
p := c.getCgroupv1Path(ctr.name)
|
||||||
if err := os.Remove(p); err != nil {
|
if err := rmDirRecursively(p); err != nil {
|
||||||
lastError = errors.Wrapf(err, "remove %s", p)
|
lastError = errors.Wrapf(err, "remove %s", p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ func (c *cpuHandler) Create(ctr *CgroupControl) (bool, error) {
|
|||||||
|
|
||||||
// Destroy the cgroup
|
// Destroy the cgroup
|
||||||
func (c *cpuHandler) Destroy(ctr *CgroupControl) error {
|
func (c *cpuHandler) Destroy(ctr *CgroupControl) error {
|
||||||
return os.Remove(ctr.getCgroupv1Path(CPU))
|
return rmDirRecursively(ctr.getCgroupv1Path(CPU))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat fills a metrics structure with usage stats for the controller
|
// Stat fills a metrics structure with usage stats for the controller
|
||||||
|
@ -3,7 +3,6 @@ package cgroups
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -77,7 +76,7 @@ func (c *cpusetHandler) Create(ctr *CgroupControl) (bool, error) {
|
|||||||
|
|
||||||
// Destroy the cgroup
|
// Destroy the cgroup
|
||||||
func (c *cpusetHandler) Destroy(ctr *CgroupControl) error {
|
func (c *cpusetHandler) Destroy(ctr *CgroupControl) error {
|
||||||
return os.Remove(ctr.getCgroupv1Path(CPUset))
|
return rmDirRecursively(ctr.getCgroupv1Path(CPUset))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat fills a metrics structure with usage stats for the controller
|
// Stat fills a metrics structure with usage stats for the controller
|
||||||
|
@ -2,7 +2,6 @@ package cgroups
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
@ -33,7 +32,7 @@ func (c *memHandler) Create(ctr *CgroupControl) (bool, error) {
|
|||||||
|
|
||||||
// Destroy the cgroup
|
// Destroy the cgroup
|
||||||
func (c *memHandler) Destroy(ctr *CgroupControl) error {
|
func (c *memHandler) Destroy(ctr *CgroupControl) error {
|
||||||
return os.Remove(ctr.getCgroupv1Path(Memory))
|
return rmDirRecursively(ctr.getCgroupv1Path(Memory))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat fills a metrics structure with usage stats for the controller
|
// Stat fills a metrics structure with usage stats for the controller
|
||||||
|
@ -3,7 +3,6 @@ package cgroups
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
spec "github.com/opencontainers/runtime-spec/specs-go"
|
spec "github.com/opencontainers/runtime-spec/specs-go"
|
||||||
@ -40,7 +39,7 @@ func (c *pidHandler) Create(ctr *CgroupControl) (bool, error) {
|
|||||||
|
|
||||||
// Destroy the cgroup
|
// Destroy the cgroup
|
||||||
func (c *pidHandler) Destroy(ctr *CgroupControl) error {
|
func (c *pidHandler) Destroy(ctr *CgroupControl) error {
|
||||||
return os.Remove(ctr.getCgroupv1Path(Pids))
|
return rmDirRecursively(ctr.getCgroupv1Path(Pids))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stat fills a metrics structure with usage stats for the controller
|
// Stat fills a metrics structure with usage stats for the controller
|
||||||
|
@ -3,6 +3,8 @@ package integration
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
. "github.com/containers/libpod/test/utils"
|
. "github.com/containers/libpod/test/utils"
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
@ -40,6 +42,21 @@ var _ = Describe("Podman pod rm", func() {
|
|||||||
result := podmanTest.Podman([]string{"pod", "rm", podid})
|
result := podmanTest.Podman([]string{"pod", "rm", podid})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result.ExitCode()).To(Equal(0))
|
Expect(result.ExitCode()).To(Equal(0))
|
||||||
|
|
||||||
|
// Also check that we don't leak cgroups
|
||||||
|
err := filepath.Walk("/sys/fs/cgroup", func(path string, info os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !info.IsDir() {
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
}
|
||||||
|
if strings.Contains(info.Name(), podid) {
|
||||||
|
return fmt.Errorf("leaking cgroup path %s", path)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
Expect(err).To(BeNil())
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman pod rm latest pod", func() {
|
It("podman pod rm latest pod", func() {
|
||||||
|
Reference in New Issue
Block a user