From 384c2359b7adf9441e949128d58396872b30fc84 Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Fri, 29 Apr 2022 12:02:00 +0200 Subject: [PATCH] libpod: unlock containers when removing pod It solves a race where a container cleanup process launched because of the container process exiting normally would hang. It also solves a problem when running as rootless on cgroup v1 since it is not possible to force pids.max = 1 on conmon to limit spawning the cleanup process. Partially copied from https://github.com/containers/podman/pull/13403 Related to: https://github.com/containers/podman/issues/14057 [NO NEW TESTS NEEDED] it doesn't add any new functionality Signed-off-by: Giuseppe Scrivano --- libpod/runtime_pod_linux.go | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libpod/runtime_pod_linux.go b/libpod/runtime_pod_linux.go index 2bbccfdf69..62ec7df602 100644 --- a/libpod/runtime_pod_linux.go +++ b/libpod/runtime_pod_linux.go @@ -199,10 +199,15 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, // Go through and lock all containers so we can operate on them all at // once. // First loop also checks that we are ready to go ahead and remove. + containersLocked := true for _, ctr := range ctrs { ctrLock := ctr.lock ctrLock.Lock() - defer ctrLock.Unlock() + defer func() { + if containersLocked { + ctrLock.Unlock() + } + }() // If we're force-removing, no need to check status. if force { @@ -304,6 +309,12 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, } } + // let's unlock the containers so if there is any cleanup process, it can terminate its execution + for _, ctr := range ctrs { + ctr.lock.Unlock() + } + containersLocked = false + // Remove pod cgroup, if present if p.state.CgroupPath != "" { logrus.Debugf("Removing pod cgroup %s", p.state.CgroupPath) @@ -332,7 +343,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool, } } if err == nil { - if err := conmonCgroup.Delete(); err != nil { + if err = conmonCgroup.Delete(); err != nil { if removalErr == nil { removalErr = errors.Wrapf(err, "error removing pod %s conmon cgroup", p.ID()) } else {