Skip to content

feat(mem): pure resolver + strict parse + clamp for CBM_MEM_BUDGET_MB#954

Open
yangsec888 wants to merge 2 commits into
DeusData:mainfrom
yangsec888:feat/mem-budget-resolver-clamp
Open

feat(mem): pure resolver + strict parse + clamp for CBM_MEM_BUDGET_MB#954
yangsec888 wants to merge 2 commits into
DeusData:mainfrom
yangsec888:feat/mem-budget-resolver-clamp

Conversation

@yangsec888

Copy link
Copy Markdown
Contributor

Summary

Hardens the existing CBM_MEM_BUDGET_MB knob per the direction in #586 — extracts the inline budget logic into a pure, testable resolver, adds clamp-to-total-RAM and source= logging, and adds the README row it lacked. No new env var.

  • Pure resolver cbm_mem_resolve_budget(total_ram, ram_fraction, budget_mb) returns a small result struct { budget, source, clamped, invalid }. The parse + clamp now live in exactly one place; cbm_mem_init only surfaces the outcome as log lines (no second parse).
  • Strict parsing, matching the existing src/foundation/limits.c convention (errno/ERANGE, reject trailing garbage, positive-only). A fat-fingered 8GB / 512MB / 20-digit typo becomes a mem.budget.env.invalid warning + safe ram_fraction fallback instead of a silently wrong budget.
  • Overflow-safe clamp: a valid-but-huge value (e.g. 2^44 MiB) clamps to detected total RAM (mem.budget.clamped) instead of overflowing the MiB→bytes multiply and wrapping to a near-zero budget — which would pin cbm_mem_over_budget() permanently true and stall indexing. When RAM detection fails (total_ram == 0), an astronomical value caps at SIZE_MAX rather than wrapping.
  • mem.init now logs source= on both the override and fraction paths.
  • README gains the CBM_MEM_BUDGET_MB row.

Behavior

CBM_MEM_BUDGET_MB Result
unset / empty ram_fraction × total_ram (source=ram_fraction)
valid, ≤ total exactly that many MiB (source=CBM_MEM_BUDGET_MB)
valid, > total clamped to total RAM (mem.budget.clamped)
valid, > total, RAM unknown honored (caps at SIZE_MAX for astronomical values)
trailing garbage / non-numeric / ≤0 / ERANGE ignored → fraction (mem.budget.env.invalid)

Testing

  • 8 pure-resolver cases in tests/test_mem.c (fraction default, invalid fraction, override wins, clamp-to-total, total-unknown, strict-reject batch incl. 8GB/512MB/0x400/ERANGE, plus the two integer-overflow abuse guards), asserting .budget / .source / .clamped / .invalid.
  • Full ASan/UBSan test-runner mem suite: 49/49 pass.
  • clang-format --dry-run --Werror clean.

Follow-ups (out of scope — for the broader memory-policy pass)

These are cross-cutting and intentionally left for the combined memory-policy design pass mentioned in #586:

  • One typed env helper for all knobs (CBM_WORKERS, CBM_MEM_BUDGET_MB, limits.*) so every override shares identical errno/trailing/range/warn semantics. Today CBM_WORKERS (system_info.c) and limits.c use two different parsing styles.
  • Separate mechanism from policy: mem.c tracks RSS + enforces a number; a policy module (no globals) owns tiers + override + clamp, resolved once in main.c and injected — removing the init-once global and the test-only cbm_mem_set_budget_for_tests hook.
  • Doc consolidation: docs/CONFIGURATION.md's env table is a stale subset of README's; the tiers/clamp/retention/subprocess-isolation story lives only in code comments.

Signed-off-by: Sam Li yangsec888@gmail.com

…_BUDGET_MB

Fold the inline CBM_MEM_BUDGET_MB override logic in cbm_mem_init into a pure,
testable cbm_mem_resolve_budget() that returns a result struct
(budget/source/clamped/invalid), so the parse + clamp lives in exactly one
place and cbm_mem_init only surfaces the outcome as log lines.

Parsing now matches the strict src/foundation/limits.c convention (errno/ERANGE,
reject trailing garbage, positive-only): a fat-fingered value like "8GB" or a
20-digit typo becomes a warning + safe ram_fraction fallback instead of a
silently wrong budget. A valid-but-huge value clamps to detected total RAM
(logged mem.budget.clamped) rather than overflowing the MiB->bytes multiply and
wrapping to a near-zero budget (which would pin cbm_mem_over_budget() true and
stall indexing). mem.init now logs source= on both the override and fraction
paths, and the README gains the CBM_MEM_BUDGET_MB row it lacked.

Hardening of the existing DeusData#363 knob.

Signed-off-by: Sam Li <yangsec888@gmail.com>
@yangsec888 yangsec888 requested a review from DeusData as a code owner July 8, 2026 10:05
…mped CBM_MEM_BUDGET_MB

The DeusData#363 memory axis (CBM_MEM_BUDGET_MB) has shipped, so this reproduce-first
case is now a permanent GREEN guard, not an open bug. Its header claimed the
override "does not exist" and asserted the budget is honoured "regardless of
host RAM" — both stale: the resolver now clamps the override to effective
(cgroup/host) RAM. On a <4 GiB host the old 4096 MiB assertion would clamp and
falsely flip the bug board RED.

Rewrite the header to describe the shipped + clamped behaviour and drop the
override to 128 MiB, which is at/below any realistic host's RAM so it is
honoured exactly and stays stable on every runner. The clamp path itself is
unit-tested in tests/test_mem.c (resolve_budget_override_clamped_to_total).

Signed-off-by: Sam Li <yangsec888@gmail.com>
@DeusData DeusData added enhancement New feature or request stability/performance Server crashes, OOM, hangs, high CPU/memory priority/normal Standard review queue; useful PR with ordinary maintainer urgency. labels Jul 8, 2026
@DeusData

DeusData commented Jul 8, 2026

Copy link
Copy Markdown
Owner

Thanks for hardening the memory-budget knob. Triage: stability/performance improvement, normal priority. Review focus is strict parsing, sane clamping, deterministic defaults, and making sure bad env values fail local and predictable rather than surprising users.

@DeusData DeusData added this to the 0.9.1-rc milestone Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request priority/normal Standard review queue; useful PR with ordinary maintainer urgency. stability/performance Server crashes, OOM, hangs, high CPU/memory

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants