Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 26 additions & 25 deletions python/kvikio/kvikio/_lib/arr.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -130,36 +130,37 @@ cdef class Array:
self.strides_mv = None
else:
PyObject_GetBuffer(obj, &pybuf, PyBUF_FULL_RO)

if pybuf.suboffsets != NULL:
raise NotImplementedError("Suboffsets are not supported")

self.ptr = <uintptr_t>pybuf.buf
self.obj = pybuf.obj
self.readonly = <bint>pybuf.readonly
self.ndim = <Py_ssize_t>pybuf.ndim
self.itemsize = <Py_ssize_t>pybuf.itemsize

if self.ndim > 0:
self.shape_mv = new_Py_ssize_t_array(self.ndim)
memcpy(
&self.shape_mv[0],
pybuf.shape,
self.ndim * sizeof(Py_ssize_t)
)
if not PyBuffer_IsContiguous(&pybuf, b"C"):
self.strides_mv = new_Py_ssize_t_array(self.ndim)
try:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The core of this change involves adding a try for the block of code right after PyObject_GetBuffer

if pybuf.suboffsets != NULL:
raise NotImplementedError("Suboffsets are not supported")
Comment on lines +134 to +135
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example here is one exception we raise

Though it is also possible to wind up with an exception due to some bug in the code below

In any event we want to make sure normal resource cleanup can proceed as usual (without potentially causing segfaults)


self.ptr = <uintptr_t>pybuf.buf
self.obj = pybuf.obj
self.readonly = <bint>pybuf.readonly
self.ndim = <Py_ssize_t>pybuf.ndim
self.itemsize = <Py_ssize_t>pybuf.itemsize

if self.ndim > 0:
self.shape_mv = new_Py_ssize_t_array(self.ndim)
memcpy(
&self.strides_mv[0],
pybuf.strides,
&self.shape_mv[0],
pybuf.shape,
self.ndim * sizeof(Py_ssize_t)
)
if not PyBuffer_IsContiguous(&pybuf, b"C"):
self.strides_mv = new_Py_ssize_t_array(self.ndim)
memcpy(
&self.strides_mv[0],
pybuf.strides,
self.ndim * sizeof(Py_ssize_t)
)
else:
self.strides_mv = None
else:
self.shape_mv = None
self.strides_mv = None
else:
self.shape_mv = None
self.strides_mv = None
PyBuffer_Release(&pybuf)
finally:
PyBuffer_Release(&pybuf)
Comment on lines +162 to +163
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then moving the PyBuffer_Release into a finally block

That way we still release the underlying Py_buffer object if an exception is raised


cpdef bint _c_contiguous(self):
return _c_contiguous(
Expand Down
Loading