Skip to content

RUST/AGENT: fix agent deadlocks and c-strings - #1367

Merged
brminich merged 14 commits into
ai-dynamo:mainfrom
tomerg-nvidia:fix-test_etcd_metadata_exchange
Mar 17, 2026
Merged

brminich merged 14 commits into
ai-dynamo:mainfrom
tomerg-nvidia:fix-test_etcd_metadata_exchange

Conversation

@tomerg-nvidia

@tomerg-nvidia tomerg-nvidia commented Feb 25, 2026 •

Copy link
Copy Markdown
Contributor

What?

Fix a deadlock in fetch_remote_md due to locking of an already locked RwLock.
Fix several places calling c++ api with non-null terminated strings.
Make test_etcd_metadata_exchange run on ci and more consistent with the c++ version of the same test.

Why?

test_etcd_metadata_exchange was not passing before that. It was also not running in CI due to the missing etcd config.
When running it manually it hung forever because of the deadlock.

Summary by CodeRabbit

  • Chores

    • Updated copyright/licensing headers to 2025–2026
    • Bumped CI image tags used by test/build pipelines
    • Centralized ETCD startup into a shared CI helper and unified CI/test scripts
  • Refactor

    • Improved lock/resource handling to avoid redundant locking
    • Hardened string handling and remote invalidation paths for safer native calls
  • Tests

    • Switched tests to polling-based synchronization and dual-backend setups for more reliable cross-agent checks

Fix a deadlock in fetch_remote_md due to locking of an already locked
RwLock. Fix several places calling c++ api with non-null terminated
strings.

Also make test_etcd_metadata_exchange run on ci and more consistent with
the c++ version of the same test.
@copy-pr-bot

copy-pr-bot Bot commented Feb 25, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@github-actions

Copy link
Copy Markdown

👋 Hi tomerg-nvidia! Thank you for contributing to ai-dynamo/nixl.

Your PR reviewers will review your contribution then trigger the CI to test your changes.

🚀

@tomerg-nvidia

Copy link
Copy Markdown
Contributor Author

/build

1 similar comment
@ovidiusm

Copy link
Copy Markdown
Contributor

/build

@tomerg-nvidia
tomerg-nvidia marked this pull request as ready for review February 26, 2026 14:52
@coderabbitai

coderabbitai Bot commented Feb 26, 2026 •

Copy link
Copy Markdown
Contributor

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

Adds a reusable ETCD startup helper and replaces inline ETCD bootstraps in CI/test scripts; hardens Rust agent FFI by converting remote identifiers to CStrings and reusing lock guards; and updates Rust metadata tests to use cross-agent backends with polling-based synchronization and invalidation checks.

Changes

Cohort / File(s) Summary
ETCD helper
\.ci/scripts/common.sh
Added start_etcd_server(namespace_prefix) to allocate ports, set NIXL_ETCD_* env vars, launch etcd in background, store ETCD_PID, and wait for readiness via wait_for_etcd.
CI / test scripts
\.gitlab/test_rust.sh, \.gitlab/test_cpp.sh, \.gitlab/test_python.sh, \.gitlab/test_nixlbench.sh
Replaced inline etcd bootstrap with start_etcd_server "<namespace>"; test_rust.sh now sources ../.ci/scripts/common.sh, added shellcheck disable directive and an EXIT trap to kill ETCD_PID. SPDX header years updated where present.
Rust agent FFI
src/bindings/rust/src/agent.rs
Reworked remote metadata fetch/invalidation to reuse inner guard(s), convert remote names/descriptors to CString before C calls, skip/log on interior-NUL conversion failures, and reduce repeated locking.
Rust tests (metadata)
src/bindings/rust/tests/tests.rs
Tests updated to use two backends (one per agent), replaced sleeps with polling loops using Duration/Instant, added explicit cross-agent invalidation and polling-based assertions, and updated SPDX year.
CI images
.ci/jenkins/lib/build-matrix.yaml, .ci/jenkins/lib/test-matrix.yaml
Bumped CI_IMAGE_TAG value to 20260305-1 in both files.

Sequence Diagram(s)

sequenceDiagram
    participant CI as CI Script / Test Runner
    participant ETCD as ETCD Server
    participant Agent1 as Agent1 (backend1)
    participant Agent2 as Agent2 (backend2)

    CI->>ETCD: start_etcd_server("/nixl/..._ci")
    ETCD-->>CI: ready
    CI->>Agent1: launch agent1 (uses backend1)
    CI->>Agent2: launch agent2 (uses backend2)
    Agent1->>ETCD: publish metadata
    Agent2->>ETCD: poll & fetch remote metadata
    Agent2-->>Agent1: observe remote metadata
    Agent2->>ETCD: request remote invalidation
    ETCD-->>Agent1: propagate invalidation
    Agent2->>ETCD: poll until invalidation visible
    ETCD-->>Agent2: invalidation observed
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I nudged the tiny etcd gate,

ports aligned, the servers wait,
C-strings snug, no hidden bite,
locks held steady through the night,
two agents hum — the sync is great.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main changes: fixing agent deadlocks and addressing C-string handling issues in Rust bindings.
Description check ✅ Passed The description covers all required template sections with specific, actionable details about what was fixed, why it was needed, and the impact on testing and CI.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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 and usage tips.

Tip

CodeRabbit can generate a title for your PR based on the changes with custom instructions.

Set the reviews.auto_title_instructions setting to generate a title for your PR based on the changes in the PR with custom instructions.

@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: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.gitlab/test_rust.sh:
- Around line 58-60: The etcd invocation uses unquoted shell variable expansions
(NIXL_ETCD_ENDPOINTS, NIXL_ETCD_PEER_URLS) which can lead to
word-splitting/globbing; update the etcd command invocation to wrap each
variable expansion in double quotes (e.g. "--listen-client-urls
\"$NIXL_ETCD_ENDPOINTS\"" etc.) so each argument is passed intact and safe from
globbing when calling etcd.

In `@src/bindings/rust/tests/tests.rs`:
- Around line 724-735: The three fixed thread::sleep(Duration::from_secs(10))
calls are making the test slow and flaky; replace each sleep with a bounded
polling loop that checks the concrete observable condition (e.g., that agent1's
metadata is invalidated/visible in etcd after
agent1.invalidate_local_md(Some(&opt_args))? and that agent2's metadata is
invalidated after agent2.invalidate_remote_md("EtcdAgent1")?). Implement polling
using Instant::now() and a timeout (e.g., 10s) with a short sleep interval
(e.g., 50–200ms) between attempts, call the appropriate read/check method on the
agent or etcd client to verify the metadata state, break early on success, and
return an error or panic if the timeout elapses so tests fail fast instead of
waiting fixed sleeps. Ensure you replace each specific sleep that follows
invalidate_local_md and invalidate_remote_md with this polling pattern.
- Around line 705-715: The test is reusing a single OptArgs containing only
backend1 for both agents; create an agent-specific OptArgs for agent2 instead of
discarding backend2: after calling agent2.create_backend (the backend produced
by agent2.create_backend / the params from agent2.get_plugin_params), construct
a second OptArgs (via OptArgs::new) and add backend2 with
opt_args2.add_backend(&backend2), then use the first opt_args when invoking
agent1.send_local_md(...) and use opt_args2 when invoking
agent2.fetch_remote_md(...), matching the pattern used in
test_send_notification.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f133f79 and d720765.

📒 Files selected for processing (3)
  • .gitlab/test_rust.sh
  • src/bindings/rust/src/agent.rs
  • src/bindings/rust/tests/tests.rs

Comment thread .gitlab/test_rust.sh Outdated
Comment thread src/bindings/rust/tests/tests.rs
Comment thread src/bindings/rust/tests/tests.rs Outdated
Comment thread .gitlab/test_rust.sh Outdated
Comment thread src/bindings/rust/src/agent.rs Outdated
Comment thread src/bindings/rust/src/agent.rs
@tomerg-nvidia

Copy link
Copy Markdown
Contributor Author

/build

1 similar comment
@tomerg-nvidia

Copy link
Copy Markdown
Contributor Author

/build

Signed-off-by: Tomer Gilad <tgilad@nvidia.com>
@tomerg-nvidia
tomerg-nvidia requested a review from a team as a code owner February 27, 2026 10:47
@pull-request-size pull-request-size Bot added size/L and removed size/M labels Feb 27, 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.

Caution

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

⚠️ Outside diff range comments (1)
src/bindings/rust/src/agent.rs (1)

1112-1129: 🧹 Nitpick | 🔵 Trivial

CString temporary lifetime is safe but consider explicit bindings for clarity.

The pattern CString::new(remote_agent)?.as_ptr().cast() is technically safe because Rust temporaries live until the end of the enclosing statement. However, this relies on subtle lifetime semantics that can be error-prone during refactoring.

The Drop implementation (lines 1144-1153) uses a clearer pattern with explicit binding. Consider applying the same style here for consistency and maintainability:

♻️ Optional refactor for consistency
 fn invalidate_remote_md(&mut self, remote_agent: &str) -> Result<(), NixlError> {
     unsafe {
         if self.remotes.remove(remote_agent) {
+            let c_remote = CString::new(remote_agent)?;
             nixl_capi_invalidate_remote_md(
                 self.handle.as_ptr(),
-                CString::new(remote_agent)?.as_ptr().cast(),
+                c_remote.as_ptr().cast(),
             );
         } else {
             return Err(NixlError::InvalidParam);
         }
     }
     Ok(())
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/bindings/rust/src/agent.rs` around lines 1112 - 1129, In
invalidate_all_remotes (and the earlier branch that calls
nixl_capi_invalidate_remote_md with CString::new(...).as_ptr().cast()), avoid
relying on the temporary CString's end-of-statement lifetime: bind the CString
to a local variable (e.g., let c_remote = CString::new(remote)?;) and pass
c_remote.as_ptr().cast() to nixl_capi_invalidate_remote_md so the CString
remains alive for the call, matching the explicit binding style used in the Drop
implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/bindings/rust/src/agent.rs`:
- Around line 1112-1129: In invalidate_all_remotes (and the earlier branch that
calls nixl_capi_invalidate_remote_md with CString::new(...).as_ptr().cast()),
avoid relying on the temporary CString's end-of-statement lifetime: bind the
CString to a local variable (e.g., let c_remote = CString::new(remote)?;) and
pass c_remote.as_ptr().cast() to nixl_capi_invalidate_remote_md so the CString
remains alive for the call, matching the explicit binding style used in the Drop
implementation.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d720765 and 7145124.

📒 Files selected for processing (7)
  • .ci/scripts/common.sh
  • .gitlab/test_cpp.sh
  • .gitlab/test_nixlbench.sh
  • .gitlab/test_python.sh
  • .gitlab/test_rust.sh
  • src/bindings/rust/src/agent.rs
  • src/bindings/rust/tests/tests.rs

@tomerg-nvidia

Copy link
Copy Markdown
Contributor Author

/build

Signed-off-by: Tomer Gilad <tgilad@nvidia.com>
@tomerg-nvidia

Copy link
Copy Markdown
Contributor Author

/build

1 similar comment
@tomerg-nvidia

Copy link
Copy Markdown
Contributor Author

/build

@tomerg-nvidia
tomerg-nvidia requested a review from brminich March 13, 2026 16:28
@tomerg-nvidia

Copy link
Copy Markdown
Contributor Author

/build

@tomerg-nvidia

Copy link
Copy Markdown
Contributor Author

/ok to test 6af91bc

@tomerg-nvidia

Copy link
Copy Markdown
Contributor Author

/build

@tomerg-nvidia

Copy link
Copy Markdown
Contributor Author

/ok to test c958d15

@tomerg-nvidia

Copy link
Copy Markdown
Contributor Author

/build

@tomerg-nvidia

Copy link
Copy Markdown
Contributor Author

/ok to test

@copy-pr-bot

copy-pr-bot Bot commented Mar 17, 2026

Copy link
Copy Markdown

/ok to test

@tomerg-nvidia, there was an error processing your request: E1

See the following link for more information: https://docs.gha-runners.nvidia.com/cpr/e/1/

@tomerg-nvidia

Copy link
Copy Markdown
Contributor Author

/ok to test 392eb91

@brminich
brminich merged commit 87451c0 into ai-dynamo:main Mar 17, 2026
17 checks passed

This branch had an error being deployed

1 failed (outdated) and 1 inactive deployments
SWX_AWS — 392eb919 Deployed Mar 17, 2026 by copy-pr-bot[bot] via Run AWS S3 Tests #4227
GITLAB — 4f24ec29 Deployed Mar 6, 2026 by copy-pr-bot[bot] via Mirror Repository to GitLab #7402
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.

5 participants