imbajin commented on code in PR #3320:
URL: https://github.com/apache/hugegraph/pull/3320#discussion_r4247498755


##########
hugegraph-server/hugegraph-dist/src/assembly/static/bin/util.sh:
##########
@@ -413,6 +413,94 @@ function wait_for_startup() {
     return 1
 }
 
+# Return the remaining memory (MiB) under visible cgroup hard limits. Keep
+# missing/unlimited controllers empty so ordinary host sizing stays unchanged.
+function cgroup_free_memory() {
+    local root="${1:-/sys/fs/cgroup}"
+    local membership="${2:-/proc/self/cgroup}"
+    local mountinfo="${3:-/proc/self/mountinfo}"
+    local base="" path="" limit_file="" usage_file=""
+    local version=""
+    local id controllers member
+    if [[ -r "$membership" ]]; then
+        while IFS=: read -r id controllers member; do
+            if [[ ",$controllers," == *,memory,* ]]; then
+                base="$root/memory"
+                path="$member"
+                limit_file="memory.limit_in_bytes"
+                usage_file="memory.usage_in_bytes"
+                version="cgroup"
+                break
+            elif [[ "$id" == 0 && -z "$controllers" ]]; then
+                base="$root"
+                path="$member"
+                limit_file="memory.max"
+                usage_file="memory.current"
+                version="cgroup2"
+            fi
+        done < "$membership"
+    fi
+    [[ -n "$base" ]] || return 0
+
+    # Mount points and exposed roots need not use the conventional hierarchy.
+    # The kernel escapes whitespace/backslashes in mountinfo path fields.
+    local mount_root="" mountpoint=""
+    if [[ -r "$mountinfo" ]]; then
+        read -r mount_root mountpoint < <(awk -v version="$version" '
+            {
+                split($0, parts, " - ");
+                split(parts[2], tail, " ");
+                if (tail[1] == version && (version == "cgroup2" ||
+                    index("," tail[3] ",", ",memory,") > 0)) {
+                    print $4, $5;
+                    exit;
+                }
+            }' "$mountinfo") || true
+        if [[ -n "$mountpoint" ]]; then
+            printf -v base '%b' "$mountpoint"
+            printf -v mount_root '%b' "$mount_root"
+            if [[ "$mount_root" != / && "$path" == "$mount_root" ]]; then
+                path=/
+            elif [[ "$mount_root" != / && "$path" == "$mount_root/"* ]]; then
+                path="${path#"$mount_root"}"
+            fi
+        fi
+    fi
+
+    # A cgroup namespace can expose its own root while /proc still names a
+    # host-relative membership. Fall back to the visible mount root in that
+    # case; never follow a membership path out of the controller mount.
+    local dir="$base"
+    if [[ "$path" == /* && "$path" != *"/../"* && "$path" != */.. &&
+          -d "$base$path" ]]; then
+        dir="$base$path"
+        dir="${dir%/}"
+    fi
+    local limit usage available smallest=""
+    while :; do
+        limit=""
+        usage=0
+        [[ ! -r "$dir/$limit_file" ]] || read -r limit < "$dir/$limit_file" || 
true
+        [[ ! -r "$dir/$usage_file" ]] || read -r usage < "$dir/$usage_file" || 
true
+        if [[ "$limit" =~ ^[0-9]+$ ]]; then
+            [[ "$usage" =~ ^[0-9]+$ ]] || usage=0
+            # awk avoids shell integer overflow for v1's unlimited sentinel.
+            available=$(awk -v limit="$limit" -v usage="$usage" 'BEGIN {
+                remaining = limit - usage;
+                printf "%.0f\n", (remaining > 0 ? int(remaining / 1048576) : 
0);

Review Comment:
   **P2 — Do not treat all charged page cache as unavailable memory.**
   
   `memory.current` includes reclaimable file cache. A bounded fixture with a 4 
GiB hard limit and 3.75 GiB charged inactive file cache produces only 256 MiB 
and makes `calc_xmx 512 32768` exit 1. The launcher then refuses startup before 
the JVM can trigger reclamation. This differs from the existing host path, 
which includes cached memory in its available budget, and can affect restarts 
in persistent limited cgroups, including non-container binary deployments.
   
   Please account for reclaimable usage conservatively and add warm-cache 
restart coverage. I verified the calculation and startup-decision path with 
synthetic cgroup files, not an actual warm-cache/kernel-pressure run. Kernel 
memory accounting reference: 
https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html#memory-interface-files



##########
hugegraph-server/hugegraph-dist/src/assembly/static/bin/util.sh:
##########
@@ -413,6 +413,94 @@ function wait_for_startup() {
     return 1
 }
 
+# Return the remaining memory (MiB) under visible cgroup hard limits. Keep
+# missing/unlimited controllers empty so ordinary host sizing stays unchanged.
+function cgroup_free_memory() {
+    local root="${1:-/sys/fs/cgroup}"
+    local membership="${2:-/proc/self/cgroup}"
+    local mountinfo="${3:-/proc/self/mountinfo}"
+    local base="" path="" limit_file="" usage_file=""
+    local version=""
+    local id controllers member
+    if [[ -r "$membership" ]]; then
+        while IFS=: read -r id controllers member; do
+            if [[ ",$controllers," == *,memory,* ]]; then
+                base="$root/memory"
+                path="$member"
+                limit_file="memory.limit_in_bytes"
+                usage_file="memory.usage_in_bytes"
+                version="cgroup"
+                break
+            elif [[ "$id" == 0 && -z "$controllers" ]]; then
+                base="$root"
+                path="$member"
+                limit_file="memory.max"
+                usage_file="memory.current"
+                version="cgroup2"
+            fi
+        done < "$membership"
+    fi
+    [[ -n "$base" ]] || return 0
+
+    # Mount points and exposed roots need not use the conventional hierarchy.
+    # The kernel escapes whitespace/backslashes in mountinfo path fields.
+    local mount_root="" mountpoint=""
+    if [[ -r "$mountinfo" ]]; then
+        read -r mount_root mountpoint < <(awk -v version="$version" '
+            {
+                split($0, parts, " - ");
+                split(parts[2], tail, " ");
+                if (tail[1] == version && (version == "cgroup2" ||
+                    index("," tail[3] ",", ",memory,") > 0)) {
+                    print $4, $5;
+                    exit;

Review Comment:
   **P2 — Select a mount that actually maps the current membership.**
   
   At this head, the first cgroup/cgroup2 mount is selected without checking 
whether its mount root covers the process membership. I reproduced membership 
`/job` with an unrelated `/other` bind mount listed first (16 GiB) and a later 
full hierarchy containing `/job` (1 GiB limit, 256 MiB usage): the helper 
returns 16384 MiB instead of 768 MiB. Removing the unrelated mount returns 768 
MiB. On a sufficiently large host, this can produce an oversized heap; an 
unrelated small group can instead refuse startup.
   
   Please validate the candidate mount against membership and continue 
searching before applying namespace fallback. Add a regression with both 
unrelated and matching mounts. This is a bounded shell-fixture reproduction, 
not a container run.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to