Skip to content

Commit 18f660d

Browse files
committed
Make create_ipc_from_usm_pointer_size_qref sole ownership of IPC mapping
Signed-off-by: Zhan Xue <zhan.xue@intel.com>
1 parent a437863 commit 18f660d

1 file changed

Lines changed: 30 additions & 26 deletions

File tree

dpctl/memory/_memory.pyx

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,16 @@ cdef class MemoryUSMDevice(_Memory):
902902
)
903903

904904

905+
cdef void _close_ipc_ptr(DPCTLSyclUSMRef ptr, DPCTLSyclQueueRef qref) noexcept:
906+
"""Close an IPC-mapped pointer using the context derived from *qref*."""
907+
cdef DPCTLSyclContextRef ctx_ref
908+
if ptr is NULL:
909+
return
910+
ctx_ref = DPCTLQueue_GetContext(qref)
911+
DPCTLIPCMem_CloseHandle(ptr, ctx_ref)
912+
DPCTLContext_Delete(ctx_ref)
913+
914+
905915
cdef class MemoryIPCDevice(MemoryUSMDevice):
906916
"""
907917
Class representing memory object backed by an IPC-mapped USM device pointer.
@@ -915,11 +925,8 @@ cdef class MemoryIPCDevice(MemoryUSMDevice):
915925
return self._memory_ptr is NULL
916926

917927
def __dealloc__(self):
918-
cdef DPCTLSyclContextRef ctx_ref
919928
if self._memory_ptr is not NULL:
920-
ctx_ref = DPCTLQueue_GetContext(self.queue.get_queue_ref())
921-
DPCTLIPCMem_CloseHandle(self._memory_ptr, ctx_ref)
922-
DPCTLContext_Delete(ctx_ref)
929+
_close_ipc_ptr(self._memory_ptr, self.queue.get_queue_ref())
923930
self._memory_ptr = NULL
924931

925932
@staticmethod
@@ -928,14 +935,19 @@ cdef class MemoryIPCDevice(MemoryUSMDevice):
928935
Py_ssize_t nbytes,
929936
DPCTLSyclQueueRef QRef,
930937
):
931-
"""Create a MemoryIPCDevice wrapping an IPC-mapped pointer."""
938+
"""Create a MemoryIPCDevice wrapping an IPC-mapped pointer.
939+
940+
Takes **sole ownership** of *USMRef*. On any failure the mapping
941+
is closed exactly once before the exception propagates.
942+
"""
932943
cdef DPCTLSyclQueueRef QRef_copy = NULL
933944
cdef _Memory base
934945

935-
if nbytes <= 0:
936-
raise ValueError("Number of bytes must be positive")
937946
if QRef is NULL:
938947
raise TypeError("Argument DPCTLSyclQueueRef is NULL")
948+
if nbytes <= 0:
949+
_close_ipc_ptr(USMRef, QRef)
950+
raise ValueError("Number of bytes must be positive")
939951

940952
base = _Memory.__new__(_Memory)
941953
base._cinit_empty()
@@ -944,11 +956,14 @@ cdef class MemoryIPCDevice(MemoryUSMDevice):
944956

945957
QRef_copy = DPCTLQueue_Copy(QRef)
946958
if QRef_copy is NULL:
959+
_close_ipc_ptr(USMRef, QRef)
960+
base._memory_ptr = NULL
947961
raise ValueError("Referenced queue could not be copied.")
948962
try:
949963
base.queue = SyclQueue._create(QRef_copy)
950964
except dpctl.SyclQueueCreationError as sqce:
951-
base._memory_ptr = NULL # caller retains ownership of USMRef
965+
_close_ipc_ptr(USMRef, QRef)
966+
base._memory_ptr = NULL
952967
raise ValueError(
953968
"SyclQueue object could not be created from "
954969
"copy of referenced queue"
@@ -957,9 +972,8 @@ cdef class MemoryIPCDevice(MemoryUSMDevice):
957972
try:
958973
result = MemoryIPCDevice(<object>base)
959974
except Exception:
960-
# If MemoryIPCDevice.__cinit__ failed after _cinit_other copied
961-
# _memory_ptr, the partial object's __dealloc__ already closed
962-
# the IPC handle. Null base to prevent any further action.
975+
# MemoryIPCDevice.__dealloc__ already closed the IPC handle.
976+
# Null base to prevent base's dealloc from acting on it.
963977
base._memory_ptr = NULL
964978
raise
965979
base._memory_ptr = NULL # ownership fully transferred to result
@@ -1226,21 +1240,11 @@ cdef class IPCMemoryHandle:
12261240
DPCTLIPCMem_CloseHandle(mapped_ptr, ctx_ref)
12271241
raise
12281242

1229-
try:
1230-
mem = MemoryIPCDevice.create_ipc_from_usm_pointer_size_qref(
1231-
mapped_ptr, nbytes, q.get_queue_ref())
1232-
except ValueError:
1233-
# Failed before MemoryIPCDevice construction (queue copy, etc).
1234-
# Handle was NOT closed — we still own it.
1235-
DPCTLIPCMem_CloseHandle(mapped_ptr, ctx_ref)
1236-
raise
1237-
except Exception:
1238-
# Failed during MemoryIPCDevice construction.
1239-
# MemoryIPCDevice.__dealloc__ already closed the IPC handle.
1240-
# Do NOT close again to avoid double-close (undefined behavior).
1241-
raise
1242-
1243-
return mem
1243+
# Ownership of mapped_ptr transfers unconditionally to the helper.
1244+
# It will close the mapping on any failure; on success the returned
1245+
# MemoryIPCDevice owns it.
1246+
return MemoryIPCDevice.create_ipc_from_usm_pointer_size_qref(
1247+
mapped_ptr, nbytes, q.get_queue_ref())
12441248

12451249
@staticmethod
12461250
def close_mapping(MemoryUSMDevice usm_memory not None):

0 commit comments

Comments
 (0)