libpod: report cgroups deleted during Stat() call

The cgroup.Stat() operation is not atomic, so it's possible that the
cgroup is removed during the Stat() call.  Catch specific errors that
can occur when the cgroup is missing and validate the existence of the
cgroup path.
If the cgroup is not found, return a more specific error indicating
that the container has been removed.

Closes: https://github.com/containers/podman/issues/23789

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano 2024-10-29 10:42:03 +01:00
parent 3a7e1deed4
commit 1f44d0f8b2
No known key found for this signature in database
GPG Key ID: 67E38F7A8BA21772
1 changed files with 6 additions and 0 deletions

View File

@ -3,6 +3,7 @@
package libpod package libpod
import ( import (
"errors"
"fmt" "fmt"
"strings" "strings"
"syscall" "syscall"
@ -36,6 +37,11 @@ func (c *Container) getPlatformContainerStats(stats *define.ContainerStats, prev
// Ubuntu does not have swap memory in cgroups because swap is often not enabled. // Ubuntu does not have swap memory in cgroups because swap is often not enabled.
cgroupStats, err := cgroup.Stat() cgroupStats, err := cgroup.Stat()
if err != nil { if err != nil {
// cgroup.Stat() is not an atomic operation, so it is possible that the cgroup is removed
// while Stat() is running. Try to catch this case and return a more specific error.
if (errors.Is(err, unix.ENOENT) || errors.Is(err, unix.ENODEV)) && !cgroupExist(cgroupPath) {
return fmt.Errorf("cgroup %s does not exist: %w", cgroupPath, define.ErrCtrStopped)
}
return fmt.Errorf("unable to obtain cgroup stats: %w", err) return fmt.Errorf("unable to obtain cgroup stats: %w", err)
} }
conState := c.state.State conState := c.state.State