Skip to content

feat: add host PID broker client and CUDA context accounting - #251

Draft
iemAnshuman wants to merge 55 commits into
Project-HAMi:mainfrom
iemAnshuman:feat-hostpid-broker-client
Draft

feat: add host PID broker client and CUDA context accounting#251
iemAnshuman wants to merge 55 commits into
Project-HAMi:mainfrom
iemAnshuman:feat-hostpid-broker-client

Conversation

@iemAnshuman

@iemAnshuman iemAnshuman commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Related issue: Project-HAMi/HAMi#1662

Design discussion: Project-HAMi/HAMi#2244

Companion server PR: Project-HAMi/HAMi#2417

Current companion server head: 146ee027b8b0ac44c8f8b3d48581f2cf69a485e9

What this changes

This adds an optional host PID broker client to HAMi-core. When LIBVGPU_HOSTPID_BROKER=1, postInit() asks the HAMi device plugin for the caller's host PID over a Unix socket. A valid response avoids the temporary CUDA primary context probe used by the NVML discovery path.

The client accepts only /tmp/vgpulock/hostpid/broker.sock. It verifies the broker directory, read only mount, socket owner, server UID, protocol fields, deadline, and returned PID before accepting a response.

The feature is disabled by default. A new HAMi-core build without the companion server continues through the NVML fallback.

Fallback correctness

The fallback must serialize NVML discovery across independent cache files because the NVML snapshots are node wide. The correction takes one node wide lock on the trusted broker mount before the existing cache record lock. It never accepts a guessed PID.

If the broker gate is enabled but the trusted mount is missing or unsafe, host PID discovery fails clearly. It does not return to cache local discovery, which could accept a concurrently starting peer PID.

The final path hardening also checks every path component, the supported filesystem policy, permission changes while a waiter is blocked, object replacement, and one absolute deadline shared by the node and cache locks.

CUDA context accounting

Removing the temporary probe also removes its context size measurement. The broker path measures memory when the application first retains the real primary context.

Accounting maps visible CUDA ordinals to physical NVML devices by PCI identity. It keeps retain and charge state for each visible device, clears inherited state after fork(), charges nested retains once, and removes the charge after the final successful release.

Validation

  1. Current client head 4421b0970c172e343c7fb59491952b78ea9d86eb passes the GitHub library build, hook consistency, cpplint, DCO, CodeRabbit, dependency, license, and security checks.

  2. Exact public heads 8d59bf9 and 935a6de completed all 16 balanced eight GPU cuInit() cells in job 181726. Mean API wall time changed from 56.373 to 22.501 seconds at N=128 and from 130.662 to 50.288 seconds at N=300. Every worker completed. This measures cuInit() only.

  3. Jobs 181845 and 182609 show the remaining driver cost. Without admission, the broker condition took 155.152 seconds at N=128 and 792.573 seconds at N=240. The N=300 cell reached its 903.11 second deadline. All 300 broker queries completed with zero broker failures, so the timeout was after PID discovery.

  4. Fallback job 182607 tested revision b0df70a with one and eight GPU layouts at N=128 and with N=300. Every candidate cell recorded zero peer and zero external PID mappings. The candidate failed discovery clearly for 71 of 128, 116 of 128, and 290 of 300 workers in those three cells. These are correctness results, not completion or performance claims.

  5. The fallback lock tests cover owner death, live holder timeout, independent caches, fork(), exec(), and overlap. A 300 waiter owner death run completed with no premature or failed waiter.

  6. The Linux root path hardening run completed 28 recorded checks with zero failures. Its archive SHA256 is 941d0a7c3de6e4602a8c57f3e71b8c21ad3acc60cef127d07599ef8ed6f7783a. The archive covers the hardening source through 607d7e83c282f8c494b39a0c2d92e16a83bdf965. Later review and lint commits at the current public head are outside that archive.

  7. The source and evidence package passes its checksum, semantic, archive, and adversarial verifier suites. It reports 46 verified artifacts, 0 pending artifacts, and 0 failures. The package ledger SHA256 is 294637ae0abbe69115c9f900442029fa0ccb335ec08ad3e8982d17f8dea1448a.

The interim validation report records the source boundaries, A100 results, fallback result, Linux archive, and remaining Kubernetes checks.

Remaining work

  1. Real kubelet allocation with the broker enabled and disabled, DaemonSet rollout and process restart, rollback, and degradation when the socket is unavailable remain untested on an isolated NVIDIA Kubernetes node.

  2. Additional container runtimes and other GPU and driver versions remain untested. The A100 result above predates the later fallback hardening commits at the current public head.

  3. The broker removes PID discovery from the serialized path, but it does not remove primary context contention. Driver admission is an optional separate follow up and remains disabled by default.

User facing change

This adds the LIBVGPU_HOSTPID_BROKER=1 opt in. Default behavior remains unchanged.

AI assistance

I used some AI assistance for this.

Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
@hami-robot

hami-robot Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: iemAnshuman
Once this PR has been reviewed and has the lgtm label, please assign archlitchi 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

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The change adds trusted Host PID broker discovery, hardened fallback locking, PCI-based CUDA-to-NVML mapping, per-device primary-context accounting, fork handling, rollout documentation, and focused tests.

Changes

Host PID discovery and broker protocol

Layer / File(s) Summary
Broker client, protocol, trust checks, and integration
src/hostpid_broker.c, src/include/hostpid_broker.h, src/utils.c, src/libvgpu.c, src/include/libvgpu.h, test/test_hostpid_broker.c, docs/hostpid-broker-client.md
The runtime queries a trusted Unix socket with bounded I/O, validates protocol responses and filesystem trust, and falls back when broker discovery is unavailable.

Fallback locking and post-init coordination

Layer / File(s) Summary
Fallback lock and deadline-aware post-init locking
src/hostpid_fallback_lock.c, src/include/hostpid_fallback_lock.h, src/multiprocess/multiprocess_memory_limit.c, src/multiprocess/multiprocess_memory_limit.h, src/libvgpu.c, docs/postinit-lock-upgrade.md
Fallback discovery uses trusted lock paths, monotonic deadlines, ordered lock acquisition, fork cleanup, and documented migration procedures.

Device mapping and accounting

Layer / File(s) Summary
CUDA-to-NVML mapping and memory queries
src/utils.c, src/multiprocess/*, src/allocator/allocator.c, src/cuda/memory.c, src/nvml/hook.c
The runtime validates CUDA device counts and mappings, uses PCI identity for mapping, and queries NVML with physical device indices.
Primary-context accounting and fork handling
src/cuda/context.c, src/cuda/context_accounting.c, src/cuda/context_accounting.h, src/libvgpu.c, test/test_context_accounting.c
Primary-context retains and releases track per-device counts and charges, roll back failed operations, and reset inherited state after fork.

Validation and build integration

Layer / File(s) Summary
Focused concurrency and build tests
src/CMakeLists.txt, src/cuda/CMakeLists.txt, test/CMakeLists.txt, test/test_hostpid_fallback_lock.c, test/test_hostpid_fallback_race.c, test/test_postinit_owner_death.c
The build compiles the new sources and registers tests for broker validation, lock deadlines, fork cleanup, owner death, path replacement, races, and ABBA ordering.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CUDAProcess
  participant postInit
  participant BrokerClient
  participant FallbackLock
  participant NVML
  CUDAProcess->>postInit: initialize process
  postInit->>BrokerClient: request host PID
  BrokerClient-->>postInit: return PID or failure
  postInit->>FallbackLock: acquire fallback locks when required
  FallbackLock-->>postInit: return discovery synchronization
  postInit->>NVML: map devices and query process memory
  NVML-->>postInit: return validated device data
Loading

Possibly related issues

Possibly related PRs

Suggested labels: enhancement

Suggested reviewers: chaunceyjiang, archlitchi

Poem

A rabbit guards the broker gate,
Maps each device to its state.
Locks wait safely, deadlines chime,
Forked states reset every time.
Trusted paths keep records straight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the two primary additions: the host PID broker client and CUDA context accounting.
✨ 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.

Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
@iemAnshuman
iemAnshuman force-pushed the feat-hostpid-broker-client branch from 70c85e4 to 973a989 Compare August 6, 2026 19:31
@iemAnshuman
iemAnshuman marked this pull request as ready for review August 7, 2026 13:45
@coderabbitai coderabbitai Bot added the enhancement New feature or request label Aug 7, 2026

@coderabbitai coderabbitai 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.

Actionable comments posted: 11

🧹 Nitpick comments (6)
docs/hostpid-broker-client.md (1)

25-25: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Hyphenate the compound modifiers.

📝 Proposed fixes
-4. The directory is visible through a read only mount.
+4. The directory is visible through a read-only mount.
-...an index list and a GPU UUID use the same driver supplied identity.
+...an index list and a GPU UUID use the same driver-supplied identity.
-The separate post init lock migration from PR 248 has a different mixed binary constraint...
+The separate post-init lock migration from PR 248 has a different mixed-binary constraint...

Consider also linking PR 248 at Line 59 so readers can find the referenced migration.

Also applies to: 41-41, 59-59

🤖 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 `@docs/hostpid-broker-client.md` at line 25, Hyphenate compound modifiers in
the affected documentation statements, including “read-only mount” and the
corresponding occurrences. At the referenced PR mention, link PR 248 so readers
can navigate to the migration details.

Source: Linters/SAST tools

test/test_hostpid_broker.c (1)

160-165: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Bound the copy into sun_path.

socket_path is a PATH_MAX buffer, and address.sun_path holds 108 bytes. The current template produces a short path, so no overflow occurs today. Add an explicit length check so a longer template cannot overflow the destination.

♻️ Proposed refactor
     address.sun_family = AF_UNIX;
-    strcpy(address.sun_path, socket_path);
+    assert(strlen(socket_path) < sizeof(address.sun_path));
+    snprintf(address.sun_path, sizeof(address.sun_path), "%s", socket_path);
🤖 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 `@test/test_hostpid_broker.c` around lines 160 - 165, Bound the socket_path
copy in the address setup around address.sun_path so paths longer than the
destination capacity are rejected or safely truncated before strcpy is reached.
Preserve the existing AF_UNIX initialization and address_length calculation for
valid paths, using the available sun_path capacity rather than assuming the
PATH_MAX source buffer fits.

Source: Linters/SAST tools

src/hostpid_broker.c (2)

342-352: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Set the socket flags atomically.

socket() creates the descriptor, and the two fcntl calls set the flags afterwards. If another thread forks in that window, the descriptor leaks into the child. Linux accepts the flags in the type argument.

♻️ Proposed refactor
-    fd = socket(AF_UNIX, SOCK_STREAM, 0);
+    fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
     if (fd < 0) {
         return -1;
     }
-    if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0 ||
-        fcntl(fd, F_SETFL, O_NONBLOCK) != 0) {
-        saved_errno = errno;
-        close(fd);
-        errno = saved_errno;
-        return -1;
-    }

Note that SOCK_CLOEXEC and SOCK_NONBLOCK are Linux specific. Keep the fcntl path if the project must build on macOS, where the __APPLE__ branch at Line 358 suggests portability intent.

🤖 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/hostpid_broker.c` around lines 342 - 352, Update the socket creation in
the surrounding broker function to request SOCK_CLOEXEC and SOCK_NONBLOCK
atomically through the socket type on Linux, removing the post-creation fcntl
setup there. Preserve the existing fcntl fallback for the __APPLE__ portability
path and retain current errno cleanup behavior on failure.

245-281: 🔒 Security & Privacy | 🔵 Trivial | ⚡ Quick win

Validate the full ancestor chain, not just the immediate directory.

hostpid_broker_validate_trust calls lstat on the socket and on its immediate parent only. For the fixed path /tmp/vgpulock/hostpid/broker.sock, the components /tmp and /tmp/vgpulock are not validated. The kernel resolves those components, including symlinks. The check is also path based, so the path can change between validation and the connect at Line 362.

The read-only mount requirement and the SO_PEERCRED UID 0 check limit the impact. Consider hardening the traversal: open each component with openat(..., O_PATH | O_NOFOLLOW) from /, apply fstat and fstatvfs to the resulting descriptors, and then connect. This removes the symlink and rename window.

🤖 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/hostpid_broker.c` around lines 245 - 281, Harden
hostpid_broker_validate_trust and the subsequent connect flow by traversing
every socket-path component from the root with openat using O_PATH|O_NOFOLLOW,
validating each descriptor with fstat and applying the read-only check via
fstatvfs. Retain ownership, directory/socket type, and permission checks across
the full ancestor chain, then connect using the validated endpoint or otherwise
prevent path changes between validation and connect.
src/cuda/CMakeLists.txt (1)

1-1: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the duplicated hook.c entry.

hook.c is listed twice. CMake removes the duplicate, so the build still works. Delete the second entry while this line is being edited.

♻️ Proposed cleanup
-add_library(cuda_mod OBJECT context.c context_accounting.c device.c hook.c event.c hook.c memory.c stream.c graph.c)
+add_library(cuda_mod OBJECT context.c context_accounting.c device.c hook.c event.c memory.c stream.c graph.c)
🤖 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/cuda/CMakeLists.txt` at line 1, Update the source list in the cuda_mod
add_library declaration to remove the duplicated hook.c entry, keeping the
remaining source files unchanged.
test/test_context_accounting.c (1)

7-7: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

assert is removed when NDEBUG is defined.

Every check in this file uses assert. If the test target builds with NDEBUG, for example under CMAKE_BUILD_TYPE=Release, the compiler removes all checks and main returns 0 without testing anything. Add #undef NDEBUG before #include <assert.h>, or force the test target to build without NDEBUG.

♻️ Proposed change
+#undef NDEBUG
 `#include` <assert.h>

Run the following script to check the build type used for the test target:

#!/bin/bash
# Inspect the test CMake configuration and any NDEBUG handling.
fd -H 'CMakeLists.txt' | xargs rg -n 'test_context_accounting|NDEBUG|CMAKE_BUILD_TYPE|CMAKE_C_FLAGS'

Also applies to: 198-210

🤖 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 `@test/test_context_accounting.c` at line 7, Ensure assertions remain active in
test_context_accounting by undefining NDEBUG immediately before including
assert.h, or configure the test target to compile without NDEBUG. Prefer the
localized test-source change so every assert check remains effective regardless
of the build type.
🤖 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 `@docs/postinit-lock-upgrade.md`:
- Around line 26-30: Update the cache-safety procedure in the post-init lock
upgrade instructions to check active memory mappings for every effective
CUDA_DEVICE_MEMORY_SHARED_CACHE path, including generated usage.cache files and
the fallback, rather than checking only open descriptors. Do not unlink any
cache until all processes retaining mappings have exited; alternatively, require
that every process using each cache has exited before removal.
- Around line 9-15: Update the postinit lock-upgrade documentation to describe
the broker-success path from postInit() separately from the NVML fallback:
identify the validation and synchronization performed after
set_task_pid_from_broker() returns NVML_SUCCESS, and state whether host PID
discovery can overlap with the fallback. Ensure both paths are documented as
following the same cache-lock contract, or specify the required implementation
change if the trusted broker-success path is not synchronized.

In `@src/cuda/context.c`:
- Around line 85-122: Move the lazy primary-context memory measurement in
cuDevicePrimaryCtxRetain outside context_accounting_lock, or protect it with a
per-device measurement lock and in-progress flag so unrelated devices and fork
preparation are not blocked. Preserve the existing measurement and accounting
updates while ensuring only one thread performs the wait/retry sequence for a
device.
- Around line 123-133: Update the primary-context accounting path around
primary_context_record_accounted_retain so an ENODATA failure from an unmeasured
retain does not convert a successful CUDA retain into CUDA_ERROR_OUT_OF_MEMORY.
Choose and implement an explicit policy: either perform a longer bounded
measurement before failing closed, or fall back to primary_context_record_retain
and log that the retain was unmeasured; preserve normal accounting for measured
retains and other errors.

In `@src/multiprocess/multiprocess_memory_limit.c`:
- Around line 1492-1497: Synchronize the host PID transition and monitor resets
in the code surrounding the host PID assignment: update atomic slot->hostpid and
clear every slot->monitorused entry under the shared-region lock or one
equivalent generation transition. Ensure utilization watchers cannot observe the
new PID until all monitor values have been reset.

In `@src/multiprocess/multiprocess_utilization_watcher.c`:
- Line 310: Initialize all visible userutil entries to -1 before each
get_used_gpu_utilization() call, ensuring devices without reverse mappings
retain the sentinel value. Keep the existing userutil[dev] >= 0 guard so only
valid utilization samples affect token adjustments in the device loop.

In `@src/utils.c`:
- Around line 263-273: Update the measured-memory read in the loop processing
the merged pids so it uses pids_on_device[i].usedGpuMemory rather than
tmp_pids_on_device[i].usedGpuMemory. Keep the existing availability, size
validation, and context_size handling unchanged.
- Around line 306-316: Update the function around parse_cuda_visible_env() to
capture and use its parsed entry count for cuda_to_nvml_map_count instead of
assigning the cuDeviceGetCount() result. Preserve the existing CUDA call only
where needed for validation, and ensure the stored count matches the populated
cuda_to_nvml_map_array entries.
- Around line 318-375: In src/utils.c lines 318-375, define and document the
contract for map_cuda_devices_to_nvml_by_pci, including whether
CUDA_DEVICE_MAX_COUNT is a valid sentinel and ensuring every consumer, including
nvml_to_cuda_map(), is bounded by cuda_to_nvml_map_count. In src/utils.c lines
103-134, preserve the env-derived mapping before invoking
map_cuda_devices_to_nvml_by_pci and restore it whenever the broker path fails
after the PCI mapping succeeds, so set_task_pid() uses the expected mapping.
- Around line 162-181: Before the realloc size calculation in the process-query
flow, validate driver-provided count against an overflow-safe maximum and return
an appropriate error when it exceeds the bound. Confirm the NVML macro target
used by nvmlDeviceGetComputeRunningProcesses, then make the allocation type and
call entry point use the matching process-info struct version, updating the
visible nvmlProcessInfo_v1_t usage if the build resolves to v3.

In `@test/test_hostpid_broker.c`:
- Around line 7-24: Add the appropriate header or POSIX feature-test
configuration before the includes in the test source so PATH_MAX is declared
under strict C99 builds. Keep the existing PATH_MAX uses in the test unchanged,
and avoid introducing a local replacement constant.

---

Nitpick comments:
In `@docs/hostpid-broker-client.md`:
- Line 25: Hyphenate compound modifiers in the affected documentation
statements, including “read-only mount” and the corresponding occurrences. At
the referenced PR mention, link PR 248 so readers can navigate to the migration
details.

In `@src/cuda/CMakeLists.txt`:
- Line 1: Update the source list in the cuda_mod add_library declaration to
remove the duplicated hook.c entry, keeping the remaining source files
unchanged.

In `@src/hostpid_broker.c`:
- Around line 342-352: Update the socket creation in the surrounding broker
function to request SOCK_CLOEXEC and SOCK_NONBLOCK atomically through the socket
type on Linux, removing the post-creation fcntl setup there. Preserve the
existing fcntl fallback for the __APPLE__ portability path and retain current
errno cleanup behavior on failure.
- Around line 245-281: Harden hostpid_broker_validate_trust and the subsequent
connect flow by traversing every socket-path component from the root with openat
using O_PATH|O_NOFOLLOW, validating each descriptor with fstat and applying the
read-only check via fstatvfs. Retain ownership, directory/socket type, and
permission checks across the full ancestor chain, then connect using the
validated endpoint or otherwise prevent path changes between validation and
connect.

In `@test/test_context_accounting.c`:
- Line 7: Ensure assertions remain active in test_context_accounting by
undefining NDEBUG immediately before including assert.h, or configure the test
target to compile without NDEBUG. Prefer the localized test-source change so
every assert check remains effective regardless of the build type.

In `@test/test_hostpid_broker.c`:
- Around line 160-165: Bound the socket_path copy in the address setup around
address.sun_path so paths longer than the destination capacity are rejected or
safely truncated before strcpy is reached. Preserve the existing AF_UNIX
initialization and address_length calculation for valid paths, using the
available sun_path capacity rather than assuming the PATH_MAX source buffer
fits.
🪄 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: e53c1994-6610-4dde-aca5-2b37183c1b45

📥 Commits

Reviewing files that changed from the base of the PR and between 5496322 and 973a989.

📒 Files selected for processing (21)
  • docs/hostpid-broker-client.md
  • docs/postinit-lock-upgrade.md
  • src/CMakeLists.txt
  • src/allocator/allocator.c
  • src/cuda/CMakeLists.txt
  • src/cuda/context.c
  • src/cuda/context_accounting.c
  • src/cuda/context_accounting.h
  • src/cuda/memory.c
  • src/hostpid_broker.c
  • src/include/hostpid_broker.h
  • src/include/libvgpu.h
  • src/libvgpu.c
  • src/multiprocess/multiprocess_memory_limit.c
  • src/multiprocess/multiprocess_memory_limit.h
  • src/multiprocess/multiprocess_utilization_watcher.c
  • src/nvml/hook.c
  • src/utils.c
  • test/CMakeLists.txt
  • test/test_context_accounting.c
  • test/test_hostpid_broker.c

Comment thread docs/postinit-lock-upgrade.md
Comment thread docs/postinit-lock-upgrade.md Outdated
Comment thread src/cuda/context.c
Comment thread src/cuda/context.c
Comment thread src/multiprocess/multiprocess_memory_limit.c
Comment thread src/utils.c
Comment thread src/utils.c Outdated
Comment thread src/utils.c
Comment thread src/utils.c
Comment thread test/test_hostpid_broker.c
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>

@coderabbitai coderabbitai 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.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/hostpid-broker-client.md (1)

57-57: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Correct the nested-retain charge semantics.

The first retain adds one context charge. Nested retains only increase the retain count. The final successful release removes the charge. Preserve retry behavior for failed additions and removals.

🤖 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 `@docs/hostpid-broker-client.md` at line 57, Update the accounting behavior
described around the retain/release state so only the first retain adds a CUDA
context charge; nested retains must increment the retain count without adding
another charge. Keep the final successful release responsible for removing the
single charge, while preserving retry handling for failed additions and
removals.
🧹 Nitpick comments (3)
src/multiprocess/multiprocess_memory_limit.c (1)

1086-1109: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Restore the timeout errno on the unlock-failure path.

At line 1090 the code saves errno (ETIMEDOUT from postinit_deadline_remaining). On the successful-unlock path at line 1102 it restores that value. On the failed-unlock path at lines 1098-1099 it returns without restoring, so the caller observes the errno that postinit_file_lock_until left behind. Callers such as test_same_process_live_holder_timeout and src/libvgpu.c branch on the timeout errno.

♻️ Proposed change
             if (!postinit_file_lock_until(F_UNLCK, NULL)) {
                 /*
                  * Do not release the process-local guard while the
                  * process-wide record lock may still be held. This leaves
                  * the process failed closed instead of allowing overlap.
                  */
                 postinit_lock_held = 1;
+                errno = saved_errno;
                 return 0;
             }
🤖 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/multiprocess/multiprocess_memory_limit.c` around lines 1086 - 1109,
Update the failed-unlock branch in the deadline handling of the postinit lock
acquisition function to restore the saved timeout errno before returning, just
as the successful-unlock path does. Preserve postinit_lock_held and the
failed-closed behavior while ensuring callers observe the original timeout errno
when postinit_file_lock_until fails.
test/test_hostpid_fallback_race.c (1)

250-297: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the cache files that were already created when create_cache_files fails.

create_cache_files returns -1 as soon as one open call fails, and it leaves the files it already created on disk. run_case then calls rmdir(directory) at line 295, which fails because the directory is not empty. Each failure leaks a temporary directory under /tmp.

♻️ Proposed change
     if (create_cache_files(directory, cache_count, cache_paths) != 0) {
+        remove_cache_files(cache_paths, cache_count);
         rmdir(directory);
         return -1;
     }
🤖 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 `@test/test_hostpid_fallback_race.c` around lines 250 - 297, Update run_case’s
create_cache_files failure path to call remove_cache_files with the number of
files successfully created (track or otherwise derive that count), then remove
the temporary directory. Ensure partial cache files are cleaned up before rmdir
so failed setup does not leak the directory.
test/test_hostpid_fallback_lock.c (1)

45-110: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the unreachable probe helpers.

The repository invokes test_hostpid_fallback_lock without probe arguments. Remove probe_lock, probe_default_lock, and their argument branches unless an external harness requires them.

🤖 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 `@test/test_hostpid_fallback_lock.c` around lines 45 - 110, Remove the unused
probe helpers probe_lock and probe_default_lock, along with the command-line
argument branches that invoke them, from test_hostpid_fallback_lock. Keep only
the no-argument execution path used by the repository, unless a confirmed
external harness requires these probes.
🤖 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 `@docs/hostpid-broker-client.md`:
- Line 41: Update the decision-table sentence describing postInit() so a
successful broker result selects the broker path only when
LIBVGPU_HOSTPID_BROKER is enabled; otherwise retain the cache-local fallback
behavior. Do not describe successful broker selection while the gate is disabled
unless explicitly labeling it as test-only.
- Line 35: Update the deadline description in the hostpid broker client
documentation to explicitly state that the monotonic transaction deadline is 500
ms and applies across connection, request write, and response read, including
when the response trickles in.

In `@test/CMakeLists.txt`:
- Around line 89-96: Increase the CTest timeout assigned by set_tests_properties
for hostpid_fallback_lock from 10 seconds to a value providing the same margin
as hostpid_fallback_race’s 30-second alarm and 35-second timeout, so the
sequential bounded sub-tests complete reliably under CI load.

In `@test/test_hostpid_fallback_lock.c`:
- Around line 464-513: Increase the holder’s post-release sleep duration in
test_deadline_not_renewed, specifically the hold timespec used before
hostpid_fallback_lock_release, so it exceeds the waiter’s 80 ms timeout by a
substantially wider margin. Leave the synchronization and child_timeout behavior
unchanged.

In `@test/test_postinit_owner_death.c`:
- Around line 505-552: Reset ready[0] to -1 immediately after closing it in the
cleanup path of test/test_postinit_owner_death.c lines 505-552, preventing fail
cleanup from closing it again. In test/test_hostpid_fallback_lock.c lines
577-608, initialize ready as {-1, -1} and return early if pipe(ready) fails
before forking or using the descriptors.
- Around line 655-659: Update the cleanup block in test_postinit_owner_death to
release the postinit lock when cache_acquired is true by calling
unlock_postinit() before other cleanup actions, ensuring unexpected success from
lock_postinit_deadline does not retain the lock for subsequent tests.

---

Outside diff comments:
In `@docs/hostpid-broker-client.md`:
- Line 57: Update the accounting behavior described around the retain/release
state so only the first retain adds a CUDA context charge; nested retains must
increment the retain count without adding another charge. Keep the final
successful release responsible for removing the single charge, while preserving
retry handling for failed additions and removals.

---

Nitpick comments:
In `@src/multiprocess/multiprocess_memory_limit.c`:
- Around line 1086-1109: Update the failed-unlock branch in the deadline
handling of the postinit lock acquisition function to restore the saved timeout
errno before returning, just as the successful-unlock path does. Preserve
postinit_lock_held and the failed-closed behavior while ensuring callers observe
the original timeout errno when postinit_file_lock_until fails.

In `@test/test_hostpid_fallback_lock.c`:
- Around line 45-110: Remove the unused probe helpers probe_lock and
probe_default_lock, along with the command-line argument branches that invoke
them, from test_hostpid_fallback_lock. Keep only the no-argument execution path
used by the repository, unless a confirmed external harness requires these
probes.

In `@test/test_hostpid_fallback_race.c`:
- Around line 250-297: Update run_case’s create_cache_files failure path to call
remove_cache_files with the number of files successfully created (track or
otherwise derive that count), then remove the temporary directory. Ensure
partial cache files are cleaned up before rmdir so failed setup does not leak
the directory.
🪄 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: c94164c5-9d80-4a8c-8c05-8da82c7e0fc5

📥 Commits

Reviewing files that changed from the base of the PR and between 8d59bf9 and 607d7e8.

📒 Files selected for processing (13)
  • docs/hostpid-broker-client.md
  • src/CMakeLists.txt
  • src/hostpid_fallback_lock.c
  • src/include/hostpid_fallback_lock.h
  • src/include/utils.h
  • src/libvgpu.c
  • src/multiprocess/multiprocess_memory_limit.c
  • src/multiprocess/multiprocess_memory_limit.h
  • src/utils.c
  • test/CMakeLists.txt
  • test/test_hostpid_fallback_lock.c
  • test/test_hostpid_fallback_race.c
  • test/test_postinit_owner_death.c
💤 Files with no reviewable changes (2)
  • src/include/utils.h
  • src/utils.c
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/CMakeLists.txt

Comment thread docs/hostpid-broker-client.md Outdated
Comment thread docs/hostpid-broker-client.md Outdated
Comment thread test/CMakeLists.txt
Comment thread test/test_hostpid_fallback_lock.c
Comment thread test/test_postinit_owner_death.c
Comment thread test/test_postinit_owner_death.c
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
Signed-off-by: iemAnshuman <asquare567@gmail.com>
@mesutoezdil

Copy link
Copy Markdown
Contributor

resolve conflicts

…tion-local

Signed-off-by: iemAnshuman <asquare567@gmail.com>

# Conflicts:
#	src/multiprocess/multiprocess_memory_limit.c
#	test/CMakeLists.txt
@iemAnshuman

Copy link
Copy Markdown
Contributor Author

resolve conflicts

conflicts are resolved. If this PR is too large for review, I can split it into smaller prs.

@maverick-woo

maverick-woo commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Thanks for the work. Please split this into smaller, focused PRs. It would also be best to provide a complete HAMi end-to-end test covering the real workload path, not only cuInit().

@iemAnshuman

Copy link
Copy Markdown
Contributor Author

Thanks for the work. Please split this into smaller, focused PRs. It would also be best to provide a complete HAMi end-to-end test covering the real workload path, not only cuInit().

makes sense. converting to draft and splitting into context accounting, fallback lock, broker client, then the integration.

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.

3 participants