Skip to content

Commit 552dadb

Browse files
committed
fix: prevent double-close of IPC memory handle in MemoryIPCDevice
create_ipc_from_usm_pointer_size_qref(): Wrap the MemoryIPCDevice construction in try/except. On failure, null base._memory_ptr to signal that __dealloc__ already closed the handle. On success, null base._memory_ptr to prevent base's own dealloc from touching it. Also null _memory_ptr in the SyclQueueCreationError path so the caller knows it still owns the handle. IPCMemoryHandle.open(): Split the single try/except into two: - SyclQueue creation failure: handle not yet transferred, close it. - create_ipc_from_usm_pointer_size_qref raises ValueError: failed before construction (queue copy), handle not closed, close it. - Any other exception from construction: __dealloc__ already closed the handle, do NOT close again. Signed-off-by: Zhan Xue <zhan.xue@intel.com>
1 parent 3ec98e3 commit 552dadb

1 file changed

Lines changed: 24 additions & 2 deletions

File tree

dpctl/memory/_memory.pyx

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -947,12 +947,22 @@ cdef class MemoryIPCDevice(MemoryUSMDevice):
947947
try:
948948
base.queue = SyclQueue._create(QRef_copy)
949949
except dpctl.SyclQueueCreationError as sqce:
950+
base._memory_ptr = NULL # caller retains ownership of USMRef
950951
raise ValueError(
951952
"SyclQueue object could not be created from "
952953
"copy of referenced queue"
953954
) from sqce
954955

955-
return MemoryIPCDevice(<object>base)
956+
try:
957+
result = MemoryIPCDevice(<object>base)
958+
except Exception:
959+
# If MemoryIPCDevice.__cinit__ failed after _cinit_other copied
960+
# _memory_ptr, the partial object's __dealloc__ already closed
961+
# the IPC handle. Null base to prevent any further action.
962+
base._memory_ptr = NULL
963+
raise
964+
base._memory_ptr = NULL # ownership fully transferred to result
965+
return result
956966

957967

958968
def as_usm_memory(obj):
@@ -1208,11 +1218,23 @@ cdef class IPCMemoryHandle:
12081218
cdef SyclQueue q
12091219
try:
12101220
q = dpctl.SyclQueue(context, device)
1221+
except Exception:
1222+
DPCTLIPCMem_CloseHandle(mapped_ptr, ctx_ref)
1223+
raise
1224+
1225+
try:
12111226
mem = MemoryIPCDevice.create_ipc_from_usm_pointer_size_qref(
12121227
mapped_ptr, nbytes, q.get_queue_ref())
1213-
except Exception:
1228+
except ValueError:
1229+
# Failed before MemoryIPCDevice construction (queue copy, etc).
1230+
# Handle was NOT closed — we still own it.
12141231
DPCTLIPCMem_CloseHandle(mapped_ptr, ctx_ref)
12151232
raise
1233+
except Exception:
1234+
# Failed during MemoryIPCDevice construction.
1235+
# MemoryIPCDevice.__dealloc__ already closed the IPC handle.
1236+
# Do NOT close again to avoid double-close (undefined behavior).
1237+
raise
12161238

12171239
return mem
12181240

0 commit comments

Comments
 (0)