[UR][OpenCL] Break reference cycle between in-order queue and last event - #23076
Open
uditagarwal97 wants to merge 1 commit into
Open
[UR][OpenCL] Break reference cycle between in-order queue and last event#23076uditagarwal97 wants to merge 1 commit into
uditagarwal97 wants to merge 1 commit into
Conversation
ur_queue_handle_t_::storeLastEvent() retained the ur_event_handle_t_ it
stores, and ur_event_handle_t_'s constructor retains its queue. For an
in-order queue that is a cycle: the queue's reference count never reaches
zero, so ~ur_queue_handle_t_ never runs and the queue, its context, its
device and the event are leaked for the lifetime of the process.
storeLastEvent() is called on every enqueue to an in-order queue, so this
affects any sycl::queue created with the in_order property.
Store the cl_event instead of the UR event. The queue only needs it to
answer UR_QUEUE_INFO_EMPTY, and a cl_event holds no reference back to the
UR queue, so the cycle cannot form. That query now calls clGetEventInfo()
directly, which is already what the sibling branch for a queue with no
stored event does.
Found with an ASan+UBSan build of the runtime running the
sycl/test-e2e/Basic tests on opencl:cpu. LeakSanitizer reported the cycle
as four indirect leaks with no direct leak, which is the signature of a
reference cycle. Covered by Basic/khr_flush.cpp and
Basic/in_order_queue_status_{khr,ext_oneapi}_empty.cpp.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The ownership fix lacks a lifecycle regression test capable of detecting the original reference cycle.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Breaks the OpenCL in-order queue/event reference cycle while preserving empty-queue tracking.
Changes:
- Stores and manages a retained native
cl_event. - Queries native event completion status directly.
- Passes native events into queue tracking.
File summaries
| File | Description |
|---|---|
queue.hpp |
Replaces strong UR-event ownership with native-event ownership. |
queue.cpp |
Queries native event execution status. |
event.hpp |
Records the native event after enqueue. |
Review details
- Files reviewed: 3/3 changed files
- Comments generated: 1
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| auto UREvent = | ||
| std::make_unique<ur_event_handle_t_>(Event, cast(Context), UrQueue); | ||
| UR_RETURN_ON_FAILURE(UrQueue->storeLastEvent(cast(UREvent.get()))); | ||
| UR_RETURN_ON_FAILURE(UrQueue->storeLastEvent(Event)); |
uditagarwal97
marked this pull request as ready for review
September 1, 2026 23:24
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
ur_queue_handle_t_::storeLastEvent()retained theur_event_handle_t_it stores (queue.hpp:71), andur_event_handle_t_'s constructor retains itsQueue(event.hpp:31). For an in-order queue that is an unbreakable cycle:LastEvent(strong, viaurEventRetain)Queue(strong, viaurQueueRetain)The queue's reference count never reaches zero, so
~ur_queue_handle_t_never runs and itsurContextRelease/urDeviceReleasenever fire. The queue, its context, its device and the event are all leaked for the lifetime of the process.Proposed Fix
Store the
cl_eventinstead of the UR event, retained withclRetainEventand released in the destructor. The queue only ever needed that event to answerUR_QUEUE_INFO_EMPTY, and acl_eventholds no reference back to the UR queue, so the cycle cannot form.The
UR_QUEUE_INFO_EMPTYquery now callsclGetEventInfo(CL_EVENT_COMMAND_EXECUTION_STATUS)directly, which is the identical call the neighbouring branch for a queue with no stored event already made.How it was found
An ASan+UBSan build of the runtime running
sycl/test-e2e/Basiconopencl:cpu. LeakSanitizer reported it as four indirect leaks with no direct leak at all, which is the signature of a reference cycle (no chunk is unreferenced, so nothing qualifies as the root):The proposed fix resolves all the leaks.
Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com