diff options
author | OpenShift Merge Robot <openshift-merge-robot@users.noreply.github.com> | 2021-12-02 14:40:48 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-02 14:40:48 +0100 |
commit | b41026aec77fc7b74a45560f242be66c25af59a6 (patch) | |
tree | cd76cce7bfd771a86d0408ade8047b9d3c0c9abc /libpod | |
parent | 6b5ecde76ebb177b1ab1dd9e9555fc198ad90858 (diff) | |
parent | 3ff47748dea946775b8f4ec8e1c644c2efb3950b (diff) | |
download | podman-b41026aec77fc7b74a45560f242be66c25af59a6.tar.gz podman-b41026aec77fc7b74a45560f242be66c25af59a6.tar.bz2 podman-b41026aec77fc7b74a45560f242be66c25af59a6.zip |
Merge pull request #12469 from Luap99/ns-teardown-flake
Fix possible rootless netns cleanup race
Diffstat (limited to 'libpod')
-rw-r--r-- | libpod/networking_linux.go | 26 |
1 files changed, 13 insertions, 13 deletions
diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index 7d1214183..b734b9c95 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -322,17 +322,14 @@ func (r *RootlessNetNS) Do(toRun func() error) error { // Cleanup the rootless network namespace if needed. // It checks if we have running containers with the bridge network mode. -// Cleanup() will try to lock RootlessNetNS, therefore you have to call -// it with an unlocked lock. +// Cleanup() expects that r.Lock is locked func (r *RootlessNetNS) Cleanup(runtime *Runtime) error { _, err := os.Stat(r.dir) if os.IsNotExist(err) { // the directory does not exists no need for cleanup return nil } - r.Lock.Lock() - defer r.Lock.Unlock() - running := func(c *Container) bool { + activeNetns := func(c *Container) bool { // no bridge => no need to check if !c.config.NetMode.IsBridge() { return false @@ -352,15 +349,18 @@ func (r *RootlessNetNS) Cleanup(runtime *Runtime) error { return false } - state := c.state.State - return state == define.ContainerStateRunning + // only check for an active netns, we cannot use the container state + // because not running does not mean that the netns does not need cleanup + // only if the netns is empty we know that we do not need cleanup + return c.state.NetNS != nil } - ctrs, err := runtime.GetContainersWithoutLock(running) + ctrs, err := runtime.GetContainersWithoutLock(activeNetns) if err != nil { return err } - // no cleanup if we found containers - if len(ctrs) > 0 { + // no cleanup if we found no other containers with a netns + // we will always find one container (the container cleanup that is currently calling us) + if len(ctrs) > 1 { return nil } logrus.Debug("Cleaning up rootless network namespace") @@ -809,10 +809,10 @@ func (r *Runtime) teardownNetwork(ns string, opts types.NetworkOptions) error { if rootlessNetNS != nil { // execute the cni setup in the rootless net ns err = rootlessNetNS.Do(tearDownPod) - rootlessNetNS.Lock.Unlock() - if err == nil { - err = rootlessNetNS.Cleanup(r) + if cerr := rootlessNetNS.Cleanup(r); cerr != nil { + logrus.WithError(err).Error("failed to cleanup rootless netns") } + rootlessNetNS.Lock.Unlock() } else { err = tearDownPod() } |