fix: prevent unsigned integer underflow in NVML memory info hook#201
fix: prevent unsigned integer underflow in NVML memory info hook#201miaobyte wants to merge 2 commits into
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: miaobyte The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
34a7e14 to
4c26dce
Compare
4c26dce to
58d0f3c
Compare
When usage > limit, (limit - usage) wraps around to a massive unsigned value (~18 EB). Clamp both free and used so that free + used = total always holds, preventing corrupted values in monitoring tools. Fixes Project-HAMi#200 Signed-off-by: peng.li24 <peng.li24@nio.com> Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
58d0f3c to
668ecb8
Compare
| switch (version) { | ||
| case 1: | ||
| ((nvmlMemory_t*)memory)->free = (limit-usage); | ||
| ((nvmlMemory_t*)memory)->free = limit - clamped; |
There was a problem hiding this comment.
This silently clamps the value without logging, so operators can't tell usage actually exceeded the limit.
There was a problem hiding this comment.
Agreed, a LOG_WARN here would help operators detect when usage exceeded the limit. Something like:
size_t clamped = (usage > limit) ? limit : usage;
if (usage > limit) {
LOG_WARN("NVML meminfo: usage %lu exceeds limit %lu, clamping", usage, limit);
}|
This only fixes the NVML hook, not the CUDA hook underflow from the same issue, so closing #200 here would be premature. |
|
已收到,正在 review 你的 PR。 |
|
Thanks for the review @mesutoezdil. Agreed on both points:
@miaobyte please update when you have a chance. |
|
Warning Review limit reached
Next review available in: 53 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughCUDA and NVML memory hooks now handle usage exceeding configured limits by logging warnings, clamping usage, and reporting bounded memory values instead of errors or underflowed free memory. ChangesMemory Usage Clamping
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
b5007c1 to
b72a46f
Compare
b72a46f to
3c3d82f
Compare
cuMemGetInfo_v2: usage 超过 limit 时不再返回 INVALID_VALUE, 而是 clamp 到 limit 再计算 free memory。 nvmlDeviceGetMemoryInfo: 同样添加 clamp + 警告日志。 Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: peng.li24 <734991033@qq.com> Signed-off-by: miaobyte <lipeng@mirrorsoft.cn>
3c3d82f to
c56e601
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@src/nvml/hook.c`:
- Around line 356-369: Update the NVML memory handling around the version switch
to derive actual_limit as the minimum of the configured limit and the original
NVML-reported total. Use actual_limit for usage clamping and for the free and
total fields in both nvmlMemory_t and nvmlMemory_v2_t, and warn when usage
exceeds actual_limit.
🪄 Autofix (Beta)
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: 44929024-f7e6-470f-8905-80b61a875ce9
📒 Files selected for processing (2)
src/cuda/memory.csrc/nvml/hook.c
| if (usage > limit) { | ||
| LOG_WARN("usage(%ld) exceeds limit(%ld), clamping", usage, limit); | ||
| } | ||
| size_t clamped = (usage > limit) ? limit : usage; | ||
| switch (version) { | ||
| case 1: | ||
| ((nvmlMemory_t*)memory)->free = (limit-usage); | ||
| ((nvmlMemory_t*)memory)->free = limit - clamped; | ||
| ((nvmlMemory_t*)memory)->total = limit; | ||
| ((nvmlMemory_t*)memory)->used = usage; | ||
| ((nvmlMemory_t*)memory)->used = clamped; | ||
| return NVML_SUCCESS; | ||
| case 2: | ||
| ((nvmlMemory_v2_t *)memory)->free = (limit-usage); | ||
| ((nvmlMemory_v2_t *)memory)->free = limit - clamped; | ||
| ((nvmlMemory_v2_t *)memory)->total = limit; | ||
| ((nvmlMemory_v2_t *)memory)->used = usage; | ||
| ((nvmlMemory_v2_t *)memory)->used = clamped; |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Cap NVML’s effective limit by the physical total.
Unlike src/cuda/memory.c Lines 522-526, this path sets total = limit unconditionally. If the configured limit exceeds the underlying NVML-reported total, NVML can return physically impossible total and free values. Compute actual_limit = min(limit, original_total), clamp usage to that value, and warn when usage > actual_limit so both hooks report the same bounded memory contract.
Proposed fix
+ size_t original_total = version == 1
+ ? ((nvmlMemory_t*)memory)->total
+ : ((nvmlMemory_v2_t*)memory)->total;
+ size_t actual_limit = (limit < original_total) ? limit : original_total;
- if (usage > limit) {
- LOG_WARN("usage(%ld) exceeds limit(%ld), clamping", usage, limit);
+ if (usage > actual_limit) {
+ LOG_WARN("usage(%zu) exceeds effective limit(%zu), clamping",
+ usage, actual_limit);
}
- size_t clamped = (usage > limit) ? limit : usage;
+ size_t clamped = (usage > actual_limit) ? actual_limit : usage;
...
- ((nvmlMemory_t*)memory)->free = limit - clamped;
- ((nvmlMemory_t*)memory)->total = limit;
+ ((nvmlMemory_t*)memory)->free = actual_limit - clamped;
+ ((nvmlMemory_t*)memory)->total = actual_limit;
...
- ((nvmlMemory_v2_t *)memory)->free = limit - clamped;
- ((nvmlMemory_v2_t *)memory)->total = limit;
+ ((nvmlMemory_v2_t *)memory)->free = actual_limit - clamped;
+ ((nvmlMemory_v2_t *)memory)->total = actual_limit;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (usage > limit) { | |
| LOG_WARN("usage(%ld) exceeds limit(%ld), clamping", usage, limit); | |
| } | |
| size_t clamped = (usage > limit) ? limit : usage; | |
| switch (version) { | |
| case 1: | |
| ((nvmlMemory_t*)memory)->free = (limit-usage); | |
| ((nvmlMemory_t*)memory)->free = limit - clamped; | |
| ((nvmlMemory_t*)memory)->total = limit; | |
| ((nvmlMemory_t*)memory)->used = usage; | |
| ((nvmlMemory_t*)memory)->used = clamped; | |
| return NVML_SUCCESS; | |
| case 2: | |
| ((nvmlMemory_v2_t *)memory)->free = (limit-usage); | |
| ((nvmlMemory_v2_t *)memory)->free = limit - clamped; | |
| ((nvmlMemory_v2_t *)memory)->total = limit; | |
| ((nvmlMemory_v2_t *)memory)->used = usage; | |
| ((nvmlMemory_v2_t *)memory)->used = clamped; | |
| size_t original_total = version == 1 | |
| ? ((nvmlMemory_t*)memory)->total | |
| : ((nvmlMemory_v2_t*)memory)->total; | |
| size_t actual_limit = (limit < original_total) ? limit : original_total; | |
| if (usage > actual_limit) { | |
| LOG_WARN("usage(%zu) exceeds effective limit(%zu), clamping", | |
| usage, actual_limit); | |
| } | |
| size_t clamped = (usage > actual_limit) ? actual_limit : usage; | |
| switch (version) { | |
| case 1: | |
| ((nvmlMemory_t*)memory)->free = actual_limit - clamped; | |
| ((nvmlMemory_t*)memory)->total = actual_limit; | |
| ((nvmlMemory_t*)memory)->used = clamped; | |
| return NVML_SUCCESS; | |
| case 2: | |
| ((nvmlMemory_v2_t *)memory)->free = actual_limit - clamped; | |
| ((nvmlMemory_v2_t *)memory)->total = actual_limit; | |
| ((nvmlMemory_v2_t *)memory)->used = clamped; |
🧰 Tools
🪛 Cppcheck (2.21.0)
[warning] 357-357: If resource allocation fails, then there is a possible null pointer dereference
(nullPointerOutOfResources)
🤖 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 `@src/nvml/hook.c` around lines 356 - 369, Update the NVML memory handling
around the version switch to derive actual_limit as the minimum of the
configured limit and the original NVML-reported total. Use actual_limit for
usage clamping and for the free and total fields in both nvmlMemory_t and
nvmlMemory_v2_t, and warn when usage exceeds actual_limit.
|
done,now updated: NVML hook (
CUDA hook (
Both hooks now handle |
|
收到,我们先测试一下。 |
|
测试通过,8x RTX 3090 上编译和运行均正常。@archlitchi 可以 merge 了。 |
|
@miaobyte Thanks for the updates, LOG_WARN and the CUDA fix look good. One item from CodeRabbit's review is still open though: on the NVML side, Can you apply the same min() clamp on the NVML side before we merge? |
Summary
Fix unsigned integer underflow in
_nvmlDeviceGetMemoryInfo: when GPU memory usage exceeds the configured limit,(limit - usage)with unsignedsize_twraps to ~18 EB, breaking monitoring tools.Changes
src/nvml/hook.c: computeclamped = (usage > limit) ? limit : usage, then derive bothused = clampedandfree = limit - clamped. This guaranteesfree + used = totalalways holds andfreenever underflows.Fixes #200
🤖 Generated with Claude Code
Summary by CodeRabbit