bindings: free the dlist handle wrapper in release_xfer_dlist_handle#1829
bindings: free the dlist handle wrapper in release_xfer_dlist_handle#1829EylonKrause wants to merge 2 commits into
Conversation
nixl_capi_prep_xfer_dlist allocates the wrapper with `new nixl_capi_xfer_dlist_handle_s`, but nixl_capi_release_xfer_dlist_handle only released the inner handle via agent->inner->releasedDlistH() (which deletes the nixlDlistH) and never deleted the wrapper struct itself. The inner handle and the wrapper are distinct heap allocations, so each prep/release cycle leaked one wrapper. Delete the wrapper after releasing the inner handle. Rust's XferDlistHandle::drop calls release exactly once and never retries, so an unconditional delete here is the sole, correct teardown (no double-free). Signed-off-by: Eylon Krause <eylon1909@gmail.com>
|
👋 Hi EylonKrause! Thank you for contributing to ai-dynamo/nixl. Your PR reviewers will review your contribution then trigger the CI to test your changes. 🚀 |
📝 WalkthroughWalkthroughIn ChangesWrapper Handle Memory Fix
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~2 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
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/wrapper.cpp (1)
1430-1436: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick winFree the wrapper on the exception path too.
At Line 1431, if
releasedDlistH(...)throws, control jumps tocatch (...)anddlist_handleis never deleted, so this still leaks on exceptions.Proposed fix
try { nixl_status_t ret = agent->inner->releasedDlistH(dlist_handle->handle); delete dlist_handle; return ret == NIXL_SUCCESS ? NIXL_CAPI_SUCCESS : NIXL_CAPI_ERROR_BACKEND; } catch (...) { + delete dlist_handle; return NIXL_CAPI_ERROR_BACKEND; }🤖 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/bindings/rust/wrapper.cpp` around lines 1430 - 1436, The exception path in releasedDlistH handling leaks the dlist wrapper because dlist_handle is only deleted after the successful call. Update the try/catch around agent->inner->releasedDlistH so the wrapper is freed even when an exception is thrown, keeping the cleanup consistent with the success path and ensuring NIXL_CAPI_ERROR_BACKEND is still returned on failure.
🤖 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.
Outside diff comments:
In `@src/bindings/rust/wrapper.cpp`:
- Around line 1430-1436: The exception path in releasedDlistH handling leaks the
dlist wrapper because dlist_handle is only deleted after the successful call.
Update the try/catch around agent->inner->releasedDlistH so the wrapper is freed
even when an exception is thrown, keeping the cleanup consistent with the
success path and ensuring NIXL_CAPI_ERROR_BACKEND is still returned on failure.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: 2997fe6c-1c44-44bd-a18a-d01169f1a9ff
📒 Files selected for processing (1)
src/bindings/rust/wrapper.cpp
|
/build |
|
/ok-to-test f1ef0a3 |
|
/build |
What?
nixl_capi_prep_xfer_dlist(src/bindings/rust/wrapper.cpp) allocates the handlewrapper with
new nixl_capi_xfer_dlist_handle_s, butnixl_capi_release_xfer_dlist_handleonly released the inner handle and neverfreed the wrapper:
try { nixl_status_t ret = agent->inner->releasedDlistH(dlist_handle->handle); + delete dlist_handle; return ret == NIXL_SUCCESS ? NIXL_CAPI_SUCCESS : NIXL_CAPI_ERROR_BACKEND; }Why?
releasedDlistH()deletes the innernixlDlistH; thenixl_capi_xfer_dlist_handle_swrapper that
prepnew'd is a separate heap allocation that was never freed, soeach prep/release cycle leaks one wrapper. Rust's
XferDlistHandle::dropcalls releaseexactly once and never retries, so an unconditional
deletehere is the sole, correctteardown (no double-free).
Reproduction
Extracted LeakSanitizer reproducer of the
new wrapper/ release-frees-only-innershape (
-fsanitize=address,leak):How (verification)
wrapper.cppin-tree with-Dsanitizer=address,undefined(exit 0).
Related Issues
None.
Summary by CodeRabbit