Skip to content

Commit

Permalink
Fix a deadlock when removing pods
Browse files Browse the repository at this point in the history
The infra container would try to remove the pod, despite the pod
already being in the process of being removed - oops. Add a check
to ensure we don't try and remove the pod when called by the
`podman pod rm` command.

Also, wire up noLockPod - it wasn't previously wired in, which is
concerning, and could be related?

Finally, make a few minor fixes to un-break lint.

Signed-off-by: Matthew Heon <[email protected]>
  • Loading branch information
mheon committed Jun 1, 2023
1 parent 8cb5d39 commit ef1a22c
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 6 deletions.
12 changes: 8 additions & 4 deletions libpod/runtime_ctr.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"io/fs"
"os"
"path"
"path/filepath"
Expand Down Expand Up @@ -690,8 +691,10 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
retErr = fmt.Errorf("container %s and pod %s share lock ID %d: %w", c.ID(), pod.ID(), c.config.LockID, define.ErrWillDeadlock)
return
}
pod.lock.Lock()
defer pod.lock.Unlock()
if !noLockPod {
pod.lock.Lock()
defer pod.lock.Unlock()
}
if err := pod.updatePod(); err != nil {
retErr = err
return
Expand Down Expand Up @@ -763,7 +766,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
removedPods[depPod.ID()] = nil
}
}
if serviceForPod || c.config.IsInfra {
if (serviceForPod || c.config.IsInfra) && !removePod {
// We're going to remove the pod we are a part of.
// This will get rid of us as well, so we can just return
// immediately after.
Expand Down Expand Up @@ -946,7 +949,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
removedCtrs[c.ID()] = nil

// Deallocate the container's lock
if err := c.lock.Free(); err != nil {
if err := c.lock.Free(); err != nil && !errors.Is(err, fs.ErrNotExist) {
reportErrorf("freeing lock for container %s: %w", c.ID(), err)
}

Expand Down Expand Up @@ -978,6 +981,7 @@ func (r *Runtime) removeContainer(ctx context.Context, c *Container, force, remo
}
}

//nolint:nakedret
return
}

Expand Down
2 changes: 1 addition & 1 deletion libpod/runtime_pod_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ func (r *Runtime) removePod(ctx context.Context, p *Pod, removeCtrs, force bool,
}

// Finalize the removed containers list
for ctr, _ := range ctrsVisited {
for ctr := range ctrsVisited {
removedCtrs[ctr] = ctrErrors[ctr]
}

Expand Down
4 changes: 3 additions & 1 deletion pkg/domain/infra/abi/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ func (ic *ContainerEngine) ContainerRestart(ctx context.Context, namesOrIds []st
return reports, nil
}

//nolint:unparam
func (ic *ContainerEngine) removeContainer(ctx context.Context, ctr *libpod.Container, options entities.RmOptions) (map[string]error, map[string]error, error) {
var err error
ctrs := make(map[string]error)
Expand Down Expand Up @@ -442,6 +443,7 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,
}
mapMutex.Unlock()

// TODO: We should report removed pods back somehow.
ctrs, _, err := ic.removeContainer(ctx, c, options)

mapMutex.Lock()
Expand All @@ -458,7 +460,7 @@ func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string,

for ctr, err := range errMap {
if _, ok := ctrsMap[ctr.ID()]; ok {
logrus.Debugf("Multiple results for container %s - attempted multiple removals?", ctr)
logrus.Debugf("Multiple results for container %s - attempted multiple removals?", ctr.ID())
}
ctrsMap[ctr.ID()] = err
}
Expand Down

0 comments on commit ef1a22c

Please sign in to comment.