Skip to content

Respect VmallocTotal from /proc/meminfo as virtual address space limit - #130994

Closed
janvorli wants to merge 4 commits into
dotnet:mainfrom
janvorli:respect-vmalloctotal-limit
Closed

janvorli wants to merge 4 commits into
dotnet:mainfrom
janvorli:respect-vmalloctotal-limit

Conversation

@janvorli

Copy link
Copy Markdown
Member

While .NET runtime and GC takes into account the virtual memory limit extracted from the RLIMIT_AS, there is another limiting factor on Linux that it doesn't consider - the VmallocTotal in /proc/meminfo. This value exposes a kernel compile time constant and we've got a report of a problem when it was mere 256GB.

Add minipal_get_virtual_address_space_limit() in src/native/minipal/vmlimit.c that computes the effective virtual address space limit by taking the minimum of RLIMIT_AS and VmallocTotal from /proc/meminfo. The result is cached since these values don't change during process lifetime.

All existing RLIMIT_AS call sites in coreclr (GC, PAL, minipal doublemapping) now use this single consolidated function instead of duplicating the getrlimit logic.

Close #85556

@janvorli janvorli added this to the 11.0.0 milestone Jul 17, 2026
@janvorli
janvorli requested a review from kkokosa July 17, 2026 19:13
@janvorli janvorli self-assigned this Jul 17, 2026
Copilot AI review requested due to automatic review settings July 17, 2026 19:13
@janvorli
janvorli force-pushed the respect-vmalloctotal-limit branch from f3334ea to fb497cc Compare July 17, 2026 19:14
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 4 pipeline(s).
11 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR centralizes virtual address space limit detection on Unix by introducing a minipal helper that computes an effective limit as min(RLIMIT_AS, VmallocTotal) (Linux) and updates CoreCLR call sites (GC, PAL, minipal double-mapping) to use it instead of duplicating getrlimit logic.

Changes:

  • Add minipal_get_virtual_address_space_limit() in src/native/minipal and cache the computed value.
  • Update CoreCLR consumers (GC, PAL virtual memory, double-mapping) to use the consolidated minipal helper.
  • Wire the new minipal source file into the native build.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/native/minipal/vmlimit.h Declares new minipal helper for effective virtual address space limit.
src/native/minipal/vmlimit.c Implements limit computation (RLIMIT_AS + Linux VmallocTotal) with caching.
src/native/minipal/CMakeLists.txt Adds vmlimit.c to minipal sources on Unix hosts.
src/coreclr/pal/src/map/virtual.cpp Switches executable memory reservation sizing to use minipal VM limit helper.
src/coreclr/minipal/Unix/doublemapping.cpp Clips double-mapped memory sizing using minipal VM limit helper.
src/coreclr/gc/unix/gcenv.unix.cpp Uses minipal VM limit helper for GC VM limit and virtual load computation.
src/coreclr/gc/unix/cgroup.cpp Uses minipal VM limit helper when computing restricted physical memory limit.
Comments suppressed due to low confidence (1)

src/coreclr/pal/src/map/virtual.cpp:1642

  • initialReserveLimit is an int32_t, but it’s being assigned from a size_t computation (virtualAddressSpaceLimit * percent / 100). When the VM limit is large (e.g. 256GB VmallocTotal), this can overflow to a negative value and then be used as an allocation size later (see line 1720), potentially turning into a huge reservation after integer conversion.
    size_t virtualAddressSpaceLimit = minipal_get_virtual_address_space_limit();
    if (virtualAddressSpaceLimit != SIZE_MAX)
    {
        // By default reserve max 20% of the available virtual address space
        size_t initialExecMemoryPerc = 20;
        CLRConfigNoCache defInitialExecMemoryPerc = CLRConfigNoCache::Get("InitialExecMemoryPercent", /*noprefix*/ false, &getenv);
        if (defInitialExecMemoryPerc.IsSet())
        {
            DWORD perc;
            if (defInitialExecMemoryPerc.TryAsInteger(16, perc))
            {
                initialExecMemoryPerc = perc;
            }
        }

        initialReserveLimit = virtualAddressSpaceLimit * initialExecMemoryPerc / 100;
        if (initialReserveLimit < sizeOfAllocation)
        {
            sizeOfAllocation = initialReserveLimit;
        }

Comment thread src/native/minipal/vmlimit.c
Comment thread src/native/minipal/vmlimit.c
Comment thread src/native/minipal/vmlimit.c
Copilot AI review requested due to automatic review settings July 17, 2026 19:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

src/coreclr/pal/src/map/virtual.cpp:1642

  • initialReserveLimit is an int32_t, but it's currently assigned from a size_t calculation (virtualAddressSpaceLimit * percent / 100). With the new VmallocTotal-based limit, this can be a large finite value (e.g., hundreds of GB) and overflow/truncate when stored into int32_t, which can then flow into ReserveVirtualMemory as a negative/garbage size. Since this logic is only intended to reduce the default reservation, only set initialReserveLimit (and shrink sizeOfAllocation) when the computed value is smaller than the current sizeOfAllocation, and compute in size_t to avoid overflow.
    size_t virtualAddressSpaceLimit = minipal_get_virtual_address_space_limit();
    if (virtualAddressSpaceLimit != SIZE_MAX)
    {
        // By default reserve max 20% of the available virtual address space
        size_t initialExecMemoryPerc = 20;
        CLRConfigNoCache defInitialExecMemoryPerc = CLRConfigNoCache::Get("InitialExecMemoryPercent", /*noprefix*/ false, &getenv);
        if (defInitialExecMemoryPerc.IsSet())
        {
            DWORD perc;
            if (defInitialExecMemoryPerc.TryAsInteger(16, perc))
            {
                initialExecMemoryPerc = perc;
            }
        }

        initialReserveLimit = virtualAddressSpaceLimit * initialExecMemoryPerc / 100;
        if (initialReserveLimit < sizeOfAllocation)
        {
            sizeOfAllocation = initialReserveLimit;
        }

Comment thread src/native/minipal/vmlimit.h
Comment thread src/native/minipal/vmlimit.c Outdated
Comment on lines +6 to +10
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <sys/resource.h>
Comment thread src/native/minipal/vmlimit.c
Comment thread src/native/minipal/vmlimit.c
Copilot AI review requested due to automatic review settings July 17, 2026 20:24
@janvorli
janvorli force-pushed the respect-vmalloctotal-limit branch from fb497cc to deeb4a9 Compare July 17, 2026 20:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (1)

src/coreclr/pal/src/map/virtual.cpp:1643

  • initialReserveLimit is int32_t, but it's assigned from virtualAddressSpaceLimit * initialExecMemoryPerc / 100 (a size_t). If the VM limit is large (e.g. VmallocTotal=256GB) this overflows/truncates to a negative int32_t, and later sizeOfAllocation = initialReserveLimit can pass a negative size into ReserveVirtualMemory. Only compute/store initialReserveLimit when the computed limit is actually smaller than the current sizeOfAllocation (and therefore fits in int32_t).
    size_t virtualAddressSpaceLimit = minipal_get_virtual_address_space_limit();
    if (virtualAddressSpaceLimit != SIZE_MAX)
    {
        // By default reserve max 20% of the available virtual address space
        size_t initialExecMemoryPerc = 20;
        CLRConfigNoCache defInitialExecMemoryPerc = CLRConfigNoCache::Get("InitialExecMemoryPercent", /*noprefix*/ false, &getenv);
        if (defInitialExecMemoryPerc.IsSet())
        {
            DWORD perc;
            if (defInitialExecMemoryPerc.TryAsInteger(16, perc))
            {
                initialExecMemoryPerc = perc;
            }
        }

        initialReserveLimit = virtualAddressSpaceLimit * initialExecMemoryPerc / 100;
        if (initialReserveLimit < sizeOfAllocation)
        {
            sizeOfAllocation = initialReserveLimit;
        }
    }

Comment thread src/native/minipal/vmlimit.h
Comment thread src/native/minipal/vmlimit.c
Comment thread src/native/minipal/vmlimit.c
Comment thread src/native/minipal/vmlimit.c
Comment thread src/native/minipal/vmlimit.c
Copilot AI review requested due to automatic review settings July 17, 2026 20:30
@janvorli
janvorli force-pushed the respect-vmalloctotal-limit branch from deeb4a9 to 0d6914c Compare July 17, 2026 20:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Comment thread src/native/minipal/vmlimit.c
Comment thread src/coreclr/pal/src/map/virtual.cpp Outdated
Comment thread src/native/minipal/vmlimit.c Outdated
Comment thread src/native/minipal/vmlimit.c Outdated
Add minipal_get_virtual_address_space_limit() in src/native/minipal/vmlimit.c
that computes the effective virtual address space limit by taking the minimum
of RLIMIT_AS and VmallocTotal from /proc/meminfo. The result is cached since
these values don't change during process lifetime.

All existing RLIMIT_AS call sites in coreclr (GC, PAL, minipal doublemapping)
now use this single consolidated function instead of duplicating the getrlimit
logic.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread src/native/minipal/vmlimit.c
Copilot AI review requested due to automatic review settings July 17, 2026 21:19
@janvorli
janvorli force-pushed the respect-vmalloctotal-limit branch from 0d6914c to ba59eea Compare July 17, 2026 21:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Comment thread src/native/minipal/vmlimit.c
Comment on lines +1638 to +1643
size_t computedLimit = virtualAddressSpaceLimit * initialExecMemoryPerc / 100;
if (computedLimit > INT32_MAX)
{
computedLimit = INT32_MAX;
}
initialReserveLimit = (int32_t)computedLimit;
Comment thread src/native/minipal/vmlimit.c Outdated
Comment thread src/native/minipal/vmlimit.c Outdated
Comment thread src/native/minipal/vmlimit.c Outdated
}
#endif

#if !defined(__APPLE__) && !defined(__HAIKU__)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
#if !defined(__APPLE__) && !defined(__HAIKU__)
#if defined(TARGET_LINUX)

@github-actions

github-actions Bot commented Jul 19, 2026 •

Copy link
Copy Markdown
Contributor

Workflow state for the Holistic Review Orchestrator.

{
  "version": 5,
  "last_dispatched_commit": "ebb6e022ffadd8412056aca691f0e324dea5eab7",
  "last_dispatched_base_ref": "main",
  "last_dispatched_base_sha": "12a9b3b909af57f3d88be0d0ec422aa336ecbd7e",
  "last_reviewed_commit": "ebb6e022ffadd8412056aca691f0e324dea5eab7",
  "last_reviewed_base_ref": "main",
  "last_reviewed_base_sha": "12a9b3b909af57f3d88be0d0ec422aa336ecbd7e",
  "last_recorded_worker_run_id": "29766775008",
  "review_attempt_commit": "",
  "review_attempt_base_ref": "",
  "review_attempt_count": 0,
  "max_review_attempts": 5,
  "review_history_format": "holistic-review-disclosure-v1",
  "review_history": [
    {
      "commit": "ba59eeacaa45b1842e91073c3e40f4589479f933",
      "review_id": 4730812683
    },
    {
      "commit": "ebb6e022ffadd8412056aca691f0e324dea5eab7",
      "review_id": 4737808507
    }
  ]
}

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Holistic Review

Motivation: On Linux the effective virtual address space is bounded not only by RLIMIT_AS but also by the kernel compile-time constant VmallocTotal exposed in /proc/meminfo, which the runtime previously ignored. A reported case with only 256 GB of VmallocTotal motivated respecting this additional limit (closes #85556). The motivation is clear and well-justified.

Approach: A new minipal_get_virtual_address_space_limit() helper (src/native/minipal/vmlimit.c) computes min(RLIMIT_AS, VmallocTotal) and caches the result. The four existing coreclr call sites (GC cgroup, gcenv, minipal doublemapping, PAL virtual) are refactored to use it, removing duplicated getrlimit(RLIMIT_AS) logic. Consolidating the scattered rlimit logic into one minipal helper is a clean, sensible design that improves maintainability.

Summary: The change is well-structured and the consolidation is a net improvement. The /proc/meminfo parsing correctly handles the optional unit suffix, and the header includes <stdint.h> so SIZE_MAX is defined (addressing several review concerns about the contract macro). A couple of points are worth confirming rather than blocking: (1) the PAL site previously fell back to RLIMIT_DATA when RLIMIT_AS was undefined and that fallback is now dropped (inline finding); (2) the cached static uses a volatile size_t non-atomic pattern which the author has explicitly accepted as a benign recompute race consistent with existing minipal patterns, though volatile provides no C threading guarantee. Verdict: LGTM with one behavior-change confirmation. This is a low-risk, focused change touching only Unix VM-limit accounting.

Detailed Findings

  • src/coreclr/pal/src/map/virtual.cpp (dropped RLIMIT_DATA fallback) — see inline comment. The prior code used RLIMIT_DATA when RLIMIT_AS was unavailable; the consolidated helper only consults RLIMIT_AS. Confirm no supported target relies on the RLIMIT_DATA fallback at this site.
  • Cached-limit thread-safety (non-blocking) — cached_limit in vmlimit.c is a static volatile size_t read/written without atomics. Functionally the worst case is computing the limit twice, which the author accepts and matches existing minipal usage; strictly, volatile does not confer the intended semantics in C, and a relaxed C11 atomic (as ospagesize.c uses) would express the intent more precisely. Not a correctness blocker given the idempotent computation.

Note

This review was generated by this repository's Holistic Review agentic workflow to complement the built-in Copilot review.

Generated by Holistic Review · 72.8 AIC · ⌖ 14.9 AIC · ⊞ 10K

#endif
rlimit addressSpaceLimit;
if ((getrlimit(addressSpace, &addressSpaceLimit) == 0) && (addressSpaceLimit.rlim_cur != RLIM_INFINITY))
size_t virtualAddressSpaceLimit = minipal_get_virtual_address_space_limit();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Behavior change worth confirming is intentional: the previous code here selected RLIMIT_DATA as a fallback when RLIMIT_AS was undefined (#ifdef RLIMIT_AS ... #else int addressSpace = RLIMIT_DATA;). The new minipal_get_virtual_address_space_limit() only consults RLIMIT_AS (guarded by #ifdef RLIMIT_AS) and never falls back to RLIMIT_DATA. On any Unix target that defines RLIMIT_DATA but not RLIMIT_AS, this call site now returns SIZE_MAX and the initial executable-memory reservation silently stops being clipped by the data-segment rlimit. If no such supported target exists this is harmless, but the consolidation drops the RLIMIT_DATA path that was previously specific to this site.

Copilot AI review requested due to automatic review settings July 20, 2026 15:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/native/minipal/vmlimit.c:82

  • The Linux-only get_vmalloc_total() helper is called under #ifndef TARGET_LINUX, which both (1) prevents Linux from applying VmallocTotal and (2) breaks non-Linux builds because get_vmalloc_total is not defined there. This should be #ifdef TARGET_LINUX so the limit is only read from /proc/meminfo on Linux.
#ifndef TARGET_LINUX
    size_t vmallocTotal = get_vmalloc_total();
    if (vmallocTotal < limit)
    {
        limit = vmallocTotal;
    }
#endif // TARGET_LINUX

Comment on lines +4 to +10
#include "vmlimit.h"

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>

#include <sys/resource.h>

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Holistic Review

Motivation: The PR addresses a real problem: on some Linux configurations the usable virtual address space is capped by the kernel's VmallocTotal (visible in /proc/meminfo), which can be smaller than RLIMIT_AS. Honoring it via a new minipal_get_virtual_address_space_limit() helper is well justified and consolidates previously duplicated logic in the GC and PAL.

Approach: The refactor into src/native/minipal/vmlimit.{c,h} and reuse across gcenv.unix.cpp, virtual.cpp, cgroup.cpp, and doublemapping.cpp is sound. This re-review covers only the incremental change (commit 6f9ac8258f2c), which replaces the !defined(__APPLE__) && !defined(__HAIKU__) guards with TARGET_LINUX in vmlimit.c and gcenv.unix.cpp. Narrowing the /proc/meminfo logic to Linux is a reasonable clarification, but the guards in vmlimit.c were applied inconsistently.

Summary: ⚠️ Needs Changes. The incremental commit introduces an inverted preprocessor guard in vmlimit.c: get_vmalloc_total() is defined under #ifdef TARGET_LINUX but called under #ifndef TARGET_LINUX. This both defeats the PR's purpose on Linux (the VmallocTotal cap is never applied) and breaks the build on both Linux (unused-function warning under -Werror) and non-Linux (call to an undefined function). This must be fixed before merge. The corresponding gcenv.unix.cpp guard change (ReadMemAvailable) is correct and consistent.


Detailed Findings

❌ Inverted preprocessor guard in vmlimit.c — call site does not match definition

See the inline comment on src/native/minipal/vmlimit.c. get_vmalloc_total() is defined inside #ifdef TARGET_LINUX (line 12) but invoked inside #ifndef TARGET_LINUX (line 76). On Linux the function is defined but never called (dead code / -Werror=unused-function) and the VmallocTotal limit is silently dropped — regressing the exact behavior this PR adds. On non-Linux platforms the function is not compiled but is still called, yielding an implicit-declaration / link error. The call-site guard should be #ifdef TARGET_LINUX.

✅ gcenv.unix.cpp guard change is correct

The matching change wraps ReadMemAvailable() (definition at line 826) in #ifdef TARGET_LINUX, and its only caller at line 1110 is inside the #else // Linux branch of the __APPLE__/__FreeBSD__/__HAIKU__ chain, so definition and use remain consistent. This is functionally equivalent to the prior !__APPLE__ && !__HAIKU__ guard for the platforms that reach it and does not regress behavior.

Assessment History

  • review 4730812683 reviewed commit ba59eeacaa45. Its verdict differs from the current verdict: the incremental commit 6f9ac8258f2c swapped the platform guards and, in doing so, inverted the get_vmalloc_total call-site guard relative to its definition, turning a previously-consistent change into a merge-blocking correctness/build defect. The assessment therefore changed to Needs Changes.

Note

This review was generated by this repository's Holistic Review agentic workflow to complement the built-in Copilot review.

Generated by Holistic Review · 69.1 AIC · ⌖ 15 AIC · ⊞ 10K

Comment thread src/native/minipal/vmlimit.c Outdated
}
#endif

#ifndef TARGET_LINUX

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The guard is inverted here. get_vmalloc_total() is defined under #ifdef TARGET_LINUX (line 12), but this call site guards it with #ifndef TARGET_LINUX. The result is that the /proc/meminfo VmallocTotal limit — the entire purpose of this PR — is now never applied on Linux, and on Linux the defined-but-unused get_vmalloc_total will trigger an unused-function warning (likely -Werror). On non-Linux platforms the reverse happens: the function is not defined but is called, producing an implicit-declaration / undefined-symbol build break. This should be #ifdef TARGET_LINUX to match the definition.

Copilot AI review requested due to automatic review settings July 20, 2026 16:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (2)

src/native/minipal/vmlimit.c:79

  • Assigning addressSpaceLimit.rlim_cur directly to size_t can silently truncate/wrap on platforms where rlim_t is wider than size_t (notably 32-bit), producing an incorrect (too small) virtual address space limit. Clamp the rlimit value to SIZE_MAX before converting to size_t.
    if ((getrlimit(addressSpace, &addressSpaceLimit) == 0) && (addressSpaceLimit.rlim_cur != RLIM_INFINITY))
    {
        limit = addressSpaceLimit.rlim_cur;
    }

src/coreclr/pal/src/map/virtual.cpp:1643

  • virtualAddressSpaceLimit * initialExecMemoryPerc can overflow size_t before the division by 100, which would yield an unexpectedly small computedLimit and potentially under-reserve executable memory. Guard the multiplication (or restructure the math) to avoid overflow.
        size_t computedLimit = virtualAddressSpaceLimit * initialExecMemoryPerc / 100;
        if (computedLimit > INT32_MAX)
        {
            computedLimit = INT32_MAX;
        }
        initialReserveLimit = (int32_t)computedLimit;

Comment on lines +15 to +18
// Returns the effective virtual address space limit for the current process
// by taking the minimum of RLIMIT_AS (if set and finite) and the VmallocTotal
// value from /proc/meminfo (on Linux).
// Returns SIZE_MAX if neither limit is available or applicable.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Holistic Review

Motivation: On some Linux configurations the usable virtual address space is capped by the kernel's VmallocTotal (exposed in /proc/meminfo), which can be smaller than RLIMIT_AS and was previously ignored (closes #85556). Honoring it via a new minipal_get_virtual_address_space_limit() helper is well justified.

Approach: The PR consolidates previously duplicated getrlimit logic from the GC and PAL into src/native/minipal/vmlimit.{c,h}, computing min(RLIMIT_AS/RLIMIT_DATA, VmallocTotal) and caching the result. This re-review covers only the incremental commit 7344c7906e8a ("Fix ifdefs"), which corrects the two issues raised in prior reviews.

Summary: ✅ LGTM. The incremental commit fixes the merge-blocking defect from the previous review: the get_vmalloc_total() call site is now guarded by #ifdef TARGET_LINUX, matching its definition (previously #ifndef), so the VmallocTotal cap is applied on Linux and the code compiles on all platforms. Additionally, the getrlimit block is now wrapped in #if defined(RLIMIT_AS) || defined(RLIMIT_DATA) and selects RLIMIT_DATA when RLIMIT_AS is undefined, restoring the RLIMIT_DATA fallback flagged in the initial review. Both prior findings are resolved and this incremental change introduces no new issues. Low-risk, focused change to Unix VM-limit accounting.

Detailed Findings

No new actionable findings in the incremental scope. The change is confined to preprocessor guards in src/native/minipal/vmlimit.c and directly addresses the two previously identified concerns.

Assessment History

  • review 4730812683 reviewed commit ba59eeacaa45 with an LGTM verdict raising a RLIMIT_DATA-fallback confirmation. The current verdict is also LGTM; the assessment is effectively unchanged in motivation, approach, and risk, and the RLIMIT_DATA fallback concern is now explicitly resolved by this commit's #if defined(RLIMIT_AS) || defined(RLIMIT_DATA) guard.
  • review 4736511437 reviewed commit 6f9ac8258f2c with a Needs Changes verdict due to the inverted #ifndef TARGET_LINUX call-site guard. The current verdict changed to LGTM: the incremental commit 7344c7906e8a replaced that guard with #ifdef TARGET_LINUX, aligning the call site with the definition and eliminating both the Linux behavior regression and the cross-platform build break.

Note

This review was generated by this repository's Holistic Review agentic workflow to complement the built-in Copilot review.

Generated by Holistic Review · 46.7 AIC · ⌖ 10.8 AIC · ⊞ 10K

Copilot AI review requested due to automatic review settings July 20, 2026 17:10

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (2)

src/coreclr/pal/src/map/virtual.cpp:1642

  • virtualAddressSpaceLimit * initialExecMemoryPerc can overflow size_t before the division by 100, which would wrap and produce a much smaller computedLimit (potentially capping the initial reserve too low). This can happen when virtualAddressSpaceLimit is large but still finite (e.g., a high RLIMIT_AS) or if the config percent is set unusually high. Compute the percentage in an overflow-safe way before clamping to INT32_MAX.
        size_t computedLimit = virtualAddressSpaceLimit * initialExecMemoryPerc / 100;
        if (computedLimit > INT32_MAX)
        {
            computedLimit = INT32_MAX;
        }

src/native/minipal/vmlimit.h:18

  • The header comment says this function takes the minimum of "RLIMIT_AS / RLIMIT_DATA", but the implementation uses RLIMIT_AS if available, otherwise RLIMIT_DATA (it doesn't compare both when both exist). Please adjust the comment to reflect the actual behavior so callers understand what limit is being applied.
// Returns the effective virtual address space limit for the current process
// by taking the minimum of RLIMIT_AS / RLIMIT_DATA (if set and finite) and
// the VmallocTotal value from /proc/meminfo (on Linux).
// Returns SIZE_MAX if neither limit is available or applicable.

return foundMemAvailable;
}
#endif // !defined(__APPLE__) && !defined(__HAIKU__)
#endif // TARGET_LINUX
Comment on lines +68 to +73
#if defined(RLIMIT_AS) || defined(RLIMIT_DATA)
#ifdef RLIMIT_AS
int addressSpace = RLIMIT_AS;
#else
int addressSpace = RLIMIT_DATA;
#endif

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Holistic Review

Motivation: On some Linux configurations the usable virtual address space is capped by the kernel's VmallocTotal (exposed in /proc/meminfo), which can be smaller than RLIMIT_AS/RLIMIT_DATA and was previously ignored (closes #85556). Honoring it via a new minipal_get_virtual_address_space_limit() helper remains well justified.

Approach: The PR consolidates previously duplicated getrlimit logic from the GC and PAL into src/native/minipal/vmlimit.{c,h}, computing min(RLIMIT_AS/RLIMIT_DATA, VmallocTotal) and caching the result. This re-review covers only the incremental commit ebb6e022ffad ("PR feedback - fix comment"), which updates the header doc comment.

Summary: ✅ LGTM. The single incremental commit changes only the documentation comment on minipal_get_virtual_address_space_limit() in src/native/minipal/vmlimit.h, changing "the minimum of RLIMIT_AS (if set and finite)" to "the minimum of RLIMIT_AS / RLIMIT_DATA (if set and finite)". This is a pure comment accuracy fix with no functional change, and it correctly matches the implementation, which selects RLIMIT_AS when defined and otherwise falls back to RLIMIT_DATA under #if defined(RLIMIT_AS) || defined(RLIMIT_DATA). No new actionable findings; the cumulative assessment (motivation, approach, risk) is unchanged. Low-risk, focused change to Unix VM-limit accounting.

Detailed Findings

No new actionable findings in the incremental scope. The change is confined to a doc-comment in src/native/minipal/vmlimit.h and accurately describes the existing RLIMIT_AS/RLIMIT_DATA behavior.

Assessment History

  • review 4730812683 reviewed commit ba59eeacaa45 with an LGTM verdict raising a RLIMIT_DATA-fallback confirmation. The current verdict is also LGTM; the assessment is unchanged in motivation, approach, and risk. The RLIMIT_DATA fallback concern was resolved by a later commit and this incremental commit only clarifies the corresponding doc comment.
  • review 4737145918 reviewed commit 7344c7906e8a with an LGTM verdict after the #ifdef fixes. The current verdict is unchanged (LGTM), with motivation, approach, and risk all unchanged; the only additional change since then is the non-functional header comment correction.

Note

This review was generated by this repository's Holistic Review agentic workflow to complement the built-in Copilot review.

Generated by Holistic Review · 48.4 AIC · ⌖ 16.3 AIC · ⊞ 10K

@janvorli

janvorli commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

I am closing this one. That value I was trying to extract is actually unrelated to the user address space, it is a kernel side max VM address space. There is no way to read the kernel imposed user mode virtual address space limit on Linux.

@janvorli janvorli closed this Aug 5, 2026
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.

crash with 0x8007000E error on .NET 7.0

4 participants