[UR][L0] Fix potential memory leaks - #22938
Conversation
There was a problem hiding this comment.
Pull request overview
This PR addresses potential memory leaks in the Unified Runtime Level Zero adapter by introducing RAII guards around allocations that can be bypassed by early-return macros (e.g., ZE2UR_CALL / UR_CALL).
Changes:
- Add a guard in
urMemBufferCreateto ensure partially-createdur_bufferinstances are freed on error paths. - Refactor buffer partition creation to use
std::unique_ptr/std::make_uniqueand release ownership on success. - Add an RAII guard for
waitlist.ZeEventListinur_buffer::getBufferZeHandleso it’s deleted on all exit paths.
Suppressed comments (1)
unified-runtime/source/adapters/level_zero/memory.cpp:1916
- This function retains the context and inserts into
Context->MemAllocsbefore executing severalUR_CALL/ZE2UR_CALLoperations that can early-return. On those error paths, the retained context andMemAllocsentry will not be rolled back, causing leaks/state pollution even if theur_bufferis RAII-managed. Consider deferring the retain/MemAllocs.emplace(...)until after all fallible operations succeed (right before returning), or add a scope rollback guard that erases the map entry and releases the retained context on failure.
*Mem = v1_cast(static_cast<ur_mem_handle_t_ *>(Buffer.release()));
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
c9ed844 to
35b1ad6
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.
Suppressed comments (1)
unified-runtime/source/adapters/level_zero/memory.cpp:1864
ur_buffer's destructor does not callfree()(seeur_buffer::~ur_buffer()), so usingstd::unique_ptr<ur_buffer>here means any early-return after the buffer is created (e.g. fromUR_CALL(...)/ZE2UR_CALL(...)later in this function) willdeletethe object without releasing allocations or an owned native handle. This can introduce leaks on error paths. Use the same guard pattern asurMemBufferCreate(custom deleter callingfree()beforedelete) so cleanup happens on all returns.
std::unique_ptr<ur_buffer> Buffer;
try {
Buffer = std::make_unique<ur_buffer>(
Context, Size, Device, ur_cast<char *>(NativeMem), OwnNativeHandle);
} catch (const std::bad_alloc &) {
35b1ad6 to
31a1988
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
unified-runtime/source/adapters/level_zero/memory.cpp:1680
- The guard is still null if
new ur_buffer(...)throws. WithUR_MEM_FLAG_USE_HOST_POINTER,maybeImportUSMhas already importedHost, so an allocation/constructor failure reaches these catches without releasing that import. Release the import in both failure paths (or guard it independently until the buffer assumes ownership).
Buffer = new ur_buffer(Context, Size, HostPtrOrNull, HostPtrImported);
bufferGuard.reset(Buffer);
| std::unique_ptr<ur_buffer, void (*)(ur_buffer *)> Buffer = { | ||
| nullptr, [](ur_buffer *handle) { | ||
| if (handle) | ||
| handle->free(); | ||
| delete handle; | ||
| }}; |
Fixes #18265