Skip to content

[SYCL][E2E] Destroy the Level Zero handles interop-direct.cpp owns - #23123

Open
uditagarwal97 wants to merge 1 commit into
intel:syclfrom
uditagarwal97:udit/e2e-interop-direct-destroy-l0-handles
Open

[SYCL][E2E] Destroy the Level Zero handles interop-direct.cpp owns#23123
uditagarwal97 wants to merge 1 commit into
intel:syclfrom
uditagarwal97:udit/e2e-interop-direct-destroy-l0-handles

Conversation

@uditagarwal97

Copy link
Copy Markdown
Contributor

Bug

Adapters/level_zero/interop-direct.cpp creates a ze_context, a ze_command_queue and an immediate ze_command_list directly through the Level Zero API and never destroys any of them. All three are handed to SYCL with ext::oneapi::level_zero::ownership::keep, so destroying them is the test's own responsibility.

Under an ASan+UBSan runtime build the test fails with 20768 bytes leaked in 14 allocations (7 per RUN line, and there are two). Every frame is in the test's own main plus the vendor Level Zero driver — there is no SYCL or Unified Runtime frame anywhere in the report, so this is purely the test leaking:

ERROR: LeakSanitizer: detected memory leaks

Direct leak of 14672 byte(s) in 1 object(s) allocated from:
    #0 0x.. in operator new(unsigned long) (/usr/lib/llvm-18/lib/clang/18/lib/linux/libclang_rt.asan-x86_64.so+0x..)
    #1 0x..  (/rdrive/ref/opencl/runtime/linux/oclgpu/Kobuk-26.14.37833.4/libze_intel_gpu.so.1+0x..)
    #2 0x..  (/rdrive/ref/opencl/runtime/linux/oclgpu/Kobuk-26.14.37833.4/libze_intel_gpu.so.1+0x..)
    #3 0x..  (/rdrive/ref/opencl/runtime/linux/oclgpu/Kobuk-26.14.37833.4/libze_intel_gpu.so.1+0x..)
    #4 0x.. in zeCommandListCreateImmediate build-san/_deps/level-zero-loader-src/source/lib/ze_libapi.cpp:3420:12
    #5 0x.. in main (build-san/tools/sycl/test-e2e/Adapters/level_zero/Output/interop-direct.cpp.tmp.out+0x..)
    #6 0x.. in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #7 0x.. in __libc_start_main csu/../csu/libc-start.c:360:3
    #8 0x.. in _start (build-san/tools/sycl/test-e2e/Adapters/level_zero/Output/interop-direct.cpp.tmp.out+0x..)

Indirect leak of 4176 byte(s) in 1 object(s) allocated from:
    #0 0x.. in operator new(unsigned long) (/usr/lib/llvm-18/lib/clang/18/lib/linux/libclang_rt.asan-x86_64.so+0x..)
    #1 0x..  (/rdrive/ref/opencl/runtime/linux/oclgpu/Kobuk-26.14.37833.4/libze_intel_gpu.so.1+0x..)
    #2 0x..  (/rdrive/ref/opencl/runtime/linux/oclgpu/Kobuk-26.14.37833.4/libze_intel_gpu.so.1+0x..)
    #3 0x..  (/rdrive/ref/opencl/runtime/linux/oclgpu/Kobuk-26.14.37833.4/libze_intel_gpu.so.1+0x..)
    #4 0x..  (/rdrive/ref/opencl/runtime/linux/oclgpu/Kobuk-26.14.37833.4/libze_intel_gpu.so.1+0x..)
    #5 0x.. in zeCommandListCreateImmediate build-san/_deps/level-zero-loader-src/source/lib/ze_libapi.cpp:3420:12
    #6 0x.. in main (build-san/tools/sycl/test-e2e/Adapters/level_zero/Output/interop-direct.cpp.tmp.out+0x..)
    #7 0x.. in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #8 0x.. in __libc_start_main csu/../csu/libc-start.c:360:3
    #9 0x.. in _start (build-san/tools/sycl/test-e2e/Adapters/level_zero/Output/interop-direct.cpp.tmp.out+0x..)

Indirect leak of 1024 byte(s) in 1 object(s) allocated from:
    #0 0x.. in operator new(unsigned long) (/usr/lib/llvm-18/lib/clang/18/lib/linux/libclang_rt.asan-x86_64.so+0x..)
    #1 0x..  (/rdrive/ref/opencl/runtime/linux/oclgpu/Kobuk-26.14.37833.4/libze_intel_gpu.so.1+0x..)
    #2 0x..  (/rdrive/ref/opencl/runtime/linux/oclgpu/Kobuk-26.14.37833.4/libze_intel_gpu.so.1+0x..)
    #3 0x..  (/rdrive/ref/opencl/runtime/linux/oclgpu/Kobuk-26.14.37833.4/libze_intel_gpu.so.1+0x..)
    #4 0x..  (/rdrive/ref/opencl/runtime/linux/oclgpu/Kobuk-26.14.37833.4/libze_intel_gpu.so.1+0x..)
    #5 0x..  (/rdrive/ref/opencl/runtime/linux/oclgpu/Kobuk-26.14.37833.4/libze_intel_gpu.so.1+0x..)
... (11 more groups, same shape, from the second RUN line)

SUMMARY: AddressSanitizer: 20768 byte(s) leaked in 14 allocation(s).

Fix

Destroy the three handles the test owns.

Ordering matters: InteropContext, InteropQueueCQ and InteropQueueCL are function-scope SYCL objects, so their destructors run after the closing return. Calling zeContextDestroy just before return 0 would therefore tear the context down while SYCL objects still referencing it are alive. A small RAII holder declared before the SYCL interop objects is destroyed last, which gives the right order and also covers the eleven early return 1 paths without reindenting the body.


Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI 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.

🟢 Approval recommended

The RAII lifetime ordering correctly prevents leaks without invalidating live SYCL interop objects.

Pull request overview

Adds RAII cleanup for Level Zero handles retained with ownership::keep.

Changes:

  • Tracks context, command queue, and command list handles.
  • Destroys handles safely after dependent SYCL objects, including early-return paths.
File summaries
File Description
sycl/test-e2e/Adapters/level_zero/interop-direct.cpp Adds ordered cleanup for test-owned Level Zero resources.
Review details
  • Files reviewed: 1/1 changed files
  • Comments generated: 0
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@uditagarwal97
uditagarwal97 marked this pull request as ready for review September 8, 2026 23:26
@uditagarwal97
uditagarwal97 requested a review from a team as a code owner September 8, 2026 23:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants