Skip to content

Commit

Permalink
DOC: Document that GIL must be grabbed (and Py_IsInitialized()) (#140)
Browse files Browse the repository at this point in the history
* DOC: Document that GIL must be grabbed (and Py_IsInitialized())

I honestly don't remember if that ``Py_IsInitialized`` wasn't just
to tape over C++ related deficiencies, but I suspect there isn't
much to be avoided there...

(I.e. if we take care of the GIL for the other library, we also
have to do this check for them which would normally be their job.)

Closes gh-103

* Apply suggestions from code review

Co-authored-by: Antoine Pitrou <[email protected]>

* Update docs/source/python_spec.rst

Co-authored-by: Antoine Pitrou <[email protected]>

* Add note that this of course only applies if it uses Python objects/API

---------

Co-authored-by: Antoine Pitrou <[email protected]>
  • Loading branch information
seberg and pitrou authored Mar 22, 2024
1 parent 62100c1 commit 6764572
Showing 1 changed file with 32 additions and 0 deletions.
32 changes: 32 additions & 0 deletions docs/source/python_spec.rst
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,38 @@ C API which is called either when the refcount on the capsule named
Note: the capsule names ``"dltensor"`` and ``"used_dltensor"`` must be
statically allocated.

The ``DLManagedTensor`` deleter must ensure that sharing beyond Python
boundaries is possible, this means that the GIL must be acquired explicitly
if it uses Python objects or API.
In Python, the deleter usually needs to ``Py_DECREF()`` the original owner
and free the ``DLManagedTensor`` allocation.
For example, NumPy uses the following code to ensure sharing with arbitrary
non-Python code is safe:

.. code-block:: C
static void array_dlpack_deleter(DLManagedTensor *self)
{
/*
* Leak the Python object if the Python runtime is not available.
* This can happen if the DLPack consumer destroys the tensor late
* after Python runtime finalization (for example in case the tensor
* was indirectly kept alive by a C++ static variable).
*/
if (!Py_IsInitialized()) {
return;
}
PyGILState_STATE state = PyGILState_Ensure();
PyObject *array = (PyObject *)self->manager_ctx;
// This will also free the shape and strides as it's one allocation.
PyMem_Free(self);
Py_XDECREF(array);
PyGILState_Release(state);
}
When the ``strides`` field in the ``DLTensor`` struct is ``NULL``, it indicates a
row-major compact array. If the array is of size zero, the data pointer in
``DLTensor`` should be set to either ``NULL`` or ``0``.
Expand Down

0 comments on commit 6764572

Please sign in to comment.