diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go index b498e33bce2..67232dfa11f 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -112,6 +112,18 @@ func (c *Container) OCIState() (*specs.State, error) { return c.currentOCIState() } +// ignoreCgroupError filters out cgroup-related errors that can be ignored, +// because the container is stopped and its cgroup is gone. +func (c *Container) ignoreCgroupError(err error) error { + if err == nil { + return nil + } + if errors.Is(err, os.ErrNotExist) && c.runType() == Stopped && !c.cgroupManager.Exists() { + return nil + } + return err +} + // Processes returns the PIDs inside this container. The PIDs are in the // namespace of the calling process. // @@ -119,18 +131,8 @@ func (c *Container) OCIState() (*specs.State, error) { // unless the container state is PAUSED in which case every PID in the slice is // valid. func (c *Container) Processes() ([]int, error) { - var pids []int - status, err := c.currentStatus() - if err != nil { - return pids, err - } - // for systemd cgroup, the unit's cgroup path will be auto removed if container's all processes exited - if status == Stopped && !c.cgroupManager.Exists() { - return pids, nil - } - - pids, err = c.cgroupManager.GetAllPids() - if err != nil { + pids, err := c.cgroupManager.GetAllPids() + if err = c.ignoreCgroupError(err); err != nil { return nil, fmt.Errorf("unable to get all container pids: %w", err) } return pids, nil @@ -363,11 +365,12 @@ func (c *Container) Signal(s os.Signal, all bool) error { return err } if all { - // for systemd cgroup, the unit's cgroup path will be auto removed if container's all processes exited if status == Stopped && !c.cgroupManager.Exists() { + // Avoid calling signalAllProcesses which may print + // a warning trying to freeze a non-existing cgroup. return nil } - return signalAllProcesses(c.cgroupManager, s) + return c.ignoreCgroupError(signalAllProcesses(c.cgroupManager, s)) } // to avoid a PID reuse attack if status == Running || status == Created || status == Paused {