Skip to content

bug(monitor): Memory Leak and Unmapped Memory Hazard in Container Lister Cache Cleanup - #2511

Closed
aniket866 wants to merge 2 commits into
Project-HAMi:masterfrom
aniket866:fix/container-lister-cache-unmap
Closed

bug(monitor): Memory Leak and Unmapped Memory Hazard in Container Lister Cache Cleanup#2511
aniket866 wants to merge 2 commits into
Project-HAMi:masterfrom
aniket866:fix/container-lister-cache-unmap

Conversation

@aniket866

@aniket866 aniket866 commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Closes #2509

bug(monitor): Memory Leak and Unmapped Memory Hazard in Container Lister Cache Cleanup

Field Details
Description When containers terminate or pods are deleted, shared memory directories under /tmp/vgpu/containers/ are removed from the filesystem. However, ContainerLister.Update() deletes entries from l.containers without explicitly invoking syscall.Munmap() on the backing mmap'd byte slice.
Location pkg/monitor/nvidia/cudevshr.go (in ContainerLister.Update())
Bug / Feature Bug
Reason Deleting a pointer reference in a Go map does not unmap virtual memory pages created via syscall.Mmap(). In dense environments with high container turnover, unmapped memory regions remain allocated in RSS, causing a steady memory leak in vGPUmonitor.
Proposed Changes Add an explicit Close() or Unmap() method to ContainerUsage that calls syscall.Munmap(c.data). Call this method inside Update() prior to removing stale container entries from l.containers.

Before vs. After Architecture

flowchart LR
    subgraph Before["Before: Unmapped Memory Leak Hazard"]
        direction TB
        B1["Pod Termination Event"]
        B2["K8s Deletes Shared Dir
/tmp/vgpu/containers/pod_ctr"]
        B3["Update Loop Scans Filesystem"]
        B4["Detect Missing Directory for PodUID"]
        B5["Execute delete(l.containers, key)"]
        B6["Go Pointer Removed from Map Cache"]
        B7["CRITICAL HAZARD:
c.data NOT Unmapped"]
        B8["OS Virtual Memory Pages Retained in RSS"]
        B9["Continuous Process Memory Leak"]

        B1 --> B2
        B2 --> B3
        B3 --> B4
        B4 --> B5
        B5 --> B6
        B6 --> B7
        B7 --> B8
        B8 --> B9
    end

    Before ==>|Explicit syscall.Munmap Implementation| After

    subgraph After["After: Explicit Munmap & Safe Cleanup"]
        direction TB
        A1["Pod Termination Event"]
        A2["K8s Deletes Shared Dir
/tmp/vgpu/containers/pod_ctr"]
        A3["Update Loop Scans Filesystem"]
        A4["Detect Missing Directory for PodUID"]
        A5["Retrieve ContainerUsage Reference"]
        A6["Invoke c.Unmap()
syscall.Munmap(c.data)"]
        A7["OS Page Table Entry Released Safely"]
        A8["Set c.data = nil & c.Info = nil"]
        A9["Execute delete(l.containers, key)"]
        A10["Zero Memory Leak & Clean Cache Removal"]

        A1 --> A2
        A2 --> A3
        A3 --> A4
        A4 --> A5
        A5 --> A6
        A6 --> A7
        A7 --> A8
        A8 --> A9
        A9 --> A10
    end

    classDef danger fill:#fee2e2,stroke:#ef4444,stroke-width:2px,color:#991b1b;
    classDef success fill:#dcfce7,stroke:#22c55e,stroke-width:2px,color:#166534;
    classDef neutral fill:#f3f4f6,stroke:#4b5563,stroke-width:1.5px,color:#1f2937;

    class B7,B8,B9 danger;
    class A6,A7,A10 success;
    class B1,B2,B3,B4,B5,B6,A1,A2,A3,A4,A5,A8,A9 neutral;
Loading

Workflow & Component Diagram

graph TD
    A["ContainerLister.Update() Triggered"] --> B["Acquire l.mutex.Lock()"]
    B --> C["Read Physical Directory Entries: os.ReadDir(/tmp/vgpu/containers)"]
    C --> D["Fetch Active Pod List from K8s InformerCache"]
    D --> E["Build Set of Valid Active PodUIDs"]
    E --> F["Iterate Registered Cache Map: l.containers"]
    F --> G{"Is Container PodUID in Valid Active Set?"}
    G -- "Yes (Active)" --> H["Keep Entry in l.containers Map"]
    G -- "No (Terminated)" --> I{"Check Resync Window TTL Expiry"}
    I -- "Not Expired" --> J["Retain Container Temporarily"]
    I -- "Expired" --> K["Extract ContainerUsage Pointer"]
    K --> L["Check c.data Slice Non-Nil & Mapped"]
    L --> M["Call syscall.Munmap(c.data)"]
    M --> N{"Munmap Succeeded?"}
    N -- "Success" --> O["Clear Pointer c.data = nil"]
    N -- "Error" --> P["Log Klog Warning with Err Details"]
    O & P --> Q["Execute delete(l.containers, key)"]
    Q --> R["Log Info: Purged Container Cache & Unmapped Memory"]
    H & J & R --> S["Release l.mutex.Unlock()"]
Loading

Summary by CodeRabbit

Bug Fixes

  • Improved cleanup of container usage data when mappings are invalid, outdated, removed, or no longer needed.
  • Ensured stale usage information is cleared after successful cleanup.
  • Preserved stale entries when cleanup fails, preventing loss of tracking information.
  • Added logging when container data cannot be unmapped successfully.

Tests

  • Expanded coverage for empty, repeated, valid, and failed unmapping scenarios.
  • Added checks confirming mapped data and usage details are cleared appropriately.

…aks and unmapped memory hazards

Signed-off-by: aniket866 <iamaniketkumarmaner@gmail.com>
@hami-robot

hami-robot Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: aniket866
Once this PR has been reviewed and has the lgtm label, please assign dsfans2014 for approval. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@hami-robot hami-robot Bot added the size/M label Aug 9, 2026
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change adds ContainerUsage.Unmap, centralizes mapped-memory cleanup, clears stale mapping state, and updates container and cache cleanup paths. Tests cover nil, empty, valid, repeated, and failed unmapping.

Changes

Container mapping cleanup

Layer / File(s) Summary
Unmap lifecycle
pkg/monitor/nvidia/cudevshr.go
ContainerUsage.Unmap unmaps data and clears data and Info. Container and cache cleanup paths use it and retain entries when unmapping fails.
Unmap validation
pkg/monitor/nvidia/cudevshr_test.go
Tests cover shared cleanup, stale-container state, nil and empty usages, repeated calls, successful unmapping, and failed unmapping.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers: fouof, mesutoezdil

Poem

A rabbit maps, then unmaps with care,
Clearing old data from memory’s lair.
Nil and empty paths safely rest,
Failed unmaps keep the mapping’s nest.
Tests hop through each cleanup state. 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the memory leak and unmapped-memory cleanup bug addressed by the pull request.
Linked Issues check ✅ Passed The changes implement explicit unmapping, preserve entries after failures, clear state after success, and add tests for issue #2509.
Out of Scope Changes check ✅ Passed The production and test changes directly support the linked issue and contain no unrelated scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
pkg/monitor/nvidia/cudevshr_test.go (1)

468-496: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add a failed-unmap test.

The test covers nil, empty, successful, and repeated calls. It does not cover a non-nil syscall.Munmap error. Add a deterministic failure case and assert the returned error and the retained cleanup state. Also test ContainerLister.Update when unmapping fails.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/monitor/nvidia/cudevshr_test.go` around lines 468 - 496, Extend
Test_ContainerUsage_Unmap with a deterministic syscall.Munmap failure, asserting
the returned error and that data and Info retain the cleanup state expected
after failure. Add coverage for ContainerLister.Update using a ContainerUsage
whose unmap fails, and assert the update propagates or handles that error
according to the existing contract.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/monitor/nvidia/cudevshr.go`:
- Line 290: Update loadCache’s invalid-header and unsupported-version cleanup
paths to handle the error returned by usage.Unmap instead of discarding it.
Preserve the existing cache-format error while logging or propagating the unmap
failure alongside it, and retain a retry or equivalent cleanup path when
unmapping remains pending.
- Around line 83-90: Update ContainerUsage.Unmap to return the syscall.Munmap
error before clearing data or Info, preserving the mapping for retries when
unmapping fails. In Update, retain the container in l.containers whenever
c.Unmap() returns an error. In loadCache validation cleanup paths, propagate or
handle usage.Unmap() errors instead of discarding them, while preserving
successful cleanup behavior.

---

Nitpick comments:
In `@pkg/monitor/nvidia/cudevshr_test.go`:
- Around line 468-496: Extend Test_ContainerUsage_Unmap with a deterministic
syscall.Munmap failure, asserting the returned error and that data and Info
retain the cleanup state expected after failure. Add coverage for
ContainerLister.Update using a ContainerUsage whose unmap fails, and assert the
update propagates or handles that error according to the existing contract.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 1b97a651-e0e4-46ab-8f16-29d10e5c3ccf

📥 Commits

Reviewing files that changed from the base of the PR and between 3616313 and bf14d67.

📒 Files selected for processing (2)
  • pkg/monitor/nvidia/cudevshr.go
  • pkg/monitor/nvidia/cudevshr_test.go

Comment thread pkg/monitor/nvidia/cudevshr.go Outdated
Comment thread pkg/monitor/nvidia/cudevshr.go Outdated
@codecov

codecov Bot commented Aug 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 75.00000% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
pkg/monitor/nvidia/cudevshr.go 75.00% 2 Missing and 2 partials ⚠️
Flag Coverage Δ
unittests 64.26% <75.00%> (+0.05%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
pkg/monitor/nvidia/cudevshr.go 85.39% <75.00%> (-1.36%) ⬇️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…rors

Update ContainerUsage.Unmap to return the syscall.Munmap error before clearing data or Info, preserving the mapping for retries when unmapping fails. In Update, retain the container in l.containers whenever c.Unmap() returns an error. In loadCache validation cleanup paths, handle usage.Unmap() errors instead of discarding them. Add unit tests for unmap error handling and container retention.

Signed-off-by: aniket866 <iamaniketkumarmaner@gmail.com>
@coderabbitai coderabbitai Bot removed the enhancement label Aug 9, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/monitor/nvidia/cudevshr_test.go`:
- Around line 518-523: Update the “unmap failure preserves data and returns
error” test for ContainerUsage to initialize Info with a non-nil sentinel before
calling Unmap, then assert that the exact same Info value remains after the
error. Keep the existing data-preservation and error assertions.
- Around line 369-388: Update ContainerLister.Update so the stale directory
associated with an Unmap failure is retained, allowing subsequent updates to
discover and retry the mapping; do not remove dirName until Unmap succeeds.
Extend the “old stale dir with unmap error retains container” test to assert
that ctrDir still exists after the failed update.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fe1670a1-b126-4f30-83d0-9d6a7e7cce9b

📥 Commits

Reviewing files that changed from the base of the PR and between bf14d67 and 8fe9d78.

📒 Files selected for processing (2)
  • pkg/monitor/nvidia/cudevshr.go
  • pkg/monitor/nvidia/cudevshr_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/monitor/nvidia/cudevshr.go

Comment thread pkg/monitor/nvidia/cudevshr_test.go
Comment thread pkg/monitor/nvidia/cudevshr_test.go
@FouoF

FouoF commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Thanks for investigating the monitor cache lifecycle. The stated root cause does not match current master: the existing deletion path already calls syscall.Munmap(c.data). The proposed wrapper primarily changes what remains cached when unmap fails, without a reproduction showing that the current behavior leaks or accesses unmapped memory. Because the premise is not established and the failure semantics would change, we are closing this PR. Please reopen only with a current-head reproducer and an explicit ownership contract for unmap failure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(monitor): Memory Leak and Unmapped Memory Hazard in Container Lister Cache Cleanup

2 participants