Skip to content

Commit d537d4a

Browse files
Andy-Jostclaude
andcommitted
fix(cuda.core): reset DevicePtrHandle before raising in Buffer._init
_apply_deallocation_stream raised after deviceptr_create_with_mr, so the partially-initialised Buffer's __dealloc__ ran during exception unwinding. The DevicePtrHandle destructor invoked _mr_dealloc_callback, which caught the inner NotImplementedError from mr.deallocate and cleared the exception state, leaving Buffer._init returning NULL with no exception set (SystemError). Fix: inline the set_deallocation_stream call in _init and reset the handle before raising on failure, preventing the callback from running. Buffer_close is unaffected: if _apply_deallocation_stream raises there, the handle is preserved in place and no destructor fires. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 7e0b351 commit d537d4a

1 file changed

Lines changed: 14 additions & 1 deletion

File tree

cuda_core/cuda/core/_memory/_buffer.pyx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,10 +213,23 @@ cdef class Buffer:
213213
cdef Buffer self = Buffer.__new__(cls)
214214
cdef uintptr_t c_ptr = <uintptr_t>(int(ptr))
215215
cdef Stream s
216+
cdef cydriver.CUresult _ds_status
216217
if mr is not None:
217218
s = Stream_accept(default_stream() if stream is None else stream)
218219
self._h_ptr = deviceptr_create_with_mr(c_ptr, size, mr)
219-
_apply_deallocation_stream(self._h_ptr, s._h_stream)
220+
_ds_status = set_deallocation_stream(self._h_ptr, s._h_stream)
221+
if _ds_status != cydriver.CUresult.CUDA_SUCCESS:
222+
# Reset before raising: the DevicePtrHandle destructor would otherwise
223+
# invoke _mr_dealloc_callback, which catches any inner exception and
224+
# clears the exception state, swallowing the error we're about to raise.
225+
self._h_ptr.reset()
226+
if _ds_status == cydriver.CUresult.CUDA_ERROR_INVALID_CONTEXT:
227+
raise RuntimeError(
228+
"Cannot record a default deallocation stream when no CUDA context is "
229+
"current. Call Device.set_current() first, or pass stream= with a "
230+
"non-default Stream."
231+
)
232+
HANDLE_RETURN(_ds_status)
220233
else:
221234
self._h_ptr = deviceptr_create_with_owner(c_ptr, owner)
222235
self._size = size

0 commit comments

Comments
 (0)