From d8467c11adfd1c6c11e09f27271a0b7df315e930 Mon Sep 17 00:00:00 2001 From: Garrett Delfosse Date: Fri, 8 Dec 2023 12:46:53 -0500 Subject: [PATCH] fix: handle no memory limit in coder stat mem (#11107) --- cli/clistat/cgroup.go | 11 +++++++++++ cli/clistat/stat_internal_test.go | 23 +++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/cli/clistat/cgroup.go b/cli/clistat/cgroup.go index 8f3ad4b71c..47787748a1 100644 --- a/cli/clistat/cgroup.go +++ b/cli/clistat/cgroup.go @@ -44,6 +44,13 @@ const ( cgroupV2MemoryStat = "/sys/fs/cgroup/memory.stat" ) +const ( + // 9223372036854771712 is the highest positive signed 64-bit integer (263-1), + // rounded down to multiples of 4096 (2^12), the most common page size on x86 systems. + // This is used by docker to indicate no memory limit. + UnlimitedMemory int64 = 9223372036854771712 +) + // ContainerCPU returns the CPU usage of the container cgroup. // This is calculated as difference of two samples of the // CPU usage of the container cgroup. @@ -271,6 +278,10 @@ func (s *Statter) cGroupV1Memory(p Prefix) (*Result, error) { // Nonetheless, if it is not, assume there is no limit set. maxUsageBytes = -1 } + // Set to unlimited if we detect the unlimited docker value. + if maxUsageBytes == UnlimitedMemory { + maxUsageBytes = -1 + } // need a space after total_rss so we don't hit something else usageBytes, err := readInt64(s.fs, cgroupV1MemoryUsageBytes) diff --git a/cli/clistat/stat_internal_test.go b/cli/clistat/stat_internal_test.go index 283c455129..10a09c178f 100644 --- a/cli/clistat/stat_internal_test.go +++ b/cli/clistat/stat_internal_test.go @@ -197,6 +197,18 @@ func TestStatter(t *testing.T) { assert.Nil(t, mem.Total) assert.Equal(t, "B", mem.Unit) }) + t.Run("ContainerMemory/NoLimit", func(t *testing.T) { + t.Parallel() + fs := initFS(t, fsContainerCgroupV1DockerNoMemoryLimit) + s, err := New(WithFS(fs), withNoWait) + require.NoError(t, err) + mem, err := s.ContainerMemory(PrefixDefault) + require.NoError(t, err) + require.NotNil(t, mem) + assert.Equal(t, 268435456.0, mem.Used) + assert.Nil(t, mem.Total) + assert.Equal(t, "B", mem.Unit) + }) }) t.Run("CGroupV2", func(t *testing.T) { @@ -384,6 +396,17 @@ proc /proc/sys proc ro,nosuid,nodev,noexec,relatime 0 0`, cgroupV1MemoryUsageBytes: "536870912", cgroupV1MemoryStat: "total_inactive_file 268435456", } + fsContainerCgroupV1DockerNoMemoryLimit = map[string]string{ + procOneCgroup: "0::/docker/aa86ac98959eeedeae0ecb6e0c9ddd8ae8b97a9d0fdccccf7ea7a474f4e0bb1f", + procMounts: `overlay / overlay rw,relatime,lowerdir=/some/path:/some/path,upperdir=/some/path:/some/path,workdir=/some/path:/some/path 0 0 +proc /proc/sys proc ro,nosuid,nodev,noexec,relatime 0 0`, + cgroupV1CPUAcctUsage: "0", + cgroupV1CFSQuotaUs: "-1", + cgroupV1CFSPeriodUs: "100000", + cgroupV1MemoryMaxUsageBytes: "9223372036854771712", + cgroupV1MemoryUsageBytes: "536870912", + cgroupV1MemoryStat: "total_inactive_file 268435456", + } fsContainerCgroupV1AltPath = map[string]string{ procOneCgroup: "0::/docker/aa86ac98959eeedeae0ecb6e0c9ddd8ae8b97a9d0fdccccf7ea7a474f4e0bb1f", procMounts: `overlay / overlay rw,relatime,lowerdir=/some/path:/some/path,upperdir=/some/path:/some/path,workdir=/some/path:/some/path 0 0