Skip to content
Open
Show file tree
Hide file tree
Changes from 2 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
6 changes: 6 additions & 0 deletions docs/api_extra.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1412,13 +1412,19 @@ functions:
Py_INCREF(o);
},
[](PyObject * o) noexcept {
if (! nb::is_alive())
return;
nb::gil_scoped_acquire guard;
Py_DECREF(o);
});

// ...
}

The liveness check in the destructor is necessary in a multi-threaded
environment because when the interpreter is shutting down, trying to
(re-) take the GIL will throw a cancellation exception.

.. cpp:function:: inline void inc_ref(intrusive_base * o) noexcept

Reference counting helper function that calls ``o->inc_ref()`` if ``o`` is
Expand Down
2 changes: 2 additions & 0 deletions docs/ownership_adv.rst
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ bindings are an optional component).
Py_INCREF(o);
},
[](PyObject *o) noexcept {
if (! nb::is_alive())
return;
nb::gil_scoped_acquire guard;
Py_DECREF(o);
});
Expand Down
2 changes: 2 additions & 0 deletions include/nanobind/intrusive/counter.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ NAMESPACE_BEGIN(nanobind)
* Py_INCREF(o);
* },
* [](PyObject *o) noexcept {
* if (! nb::is_alive())
* return;
* nb::gil_scoped_acquire guard;
* Py_DECREF(o);
* });
Expand Down
2 changes: 1 addition & 1 deletion include/nanobind/stl/function.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ struct pyfunc_wrapper {
}

~pyfunc_wrapper() {
if (f) {
if (f && is_alive()) {
gil_scoped_acquire acq;
Py_DECREF(f);
}
Expand Down
4 changes: 2 additions & 2 deletions src/error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ python_error::python_error() {
}

python_error::~python_error() {
if (m_value) {
if (m_value && detail::is_alive()) {
gil_scoped_acquire acq;
/* With GIL held */ {
// Clear error status in case the following executes Python code
Expand Down Expand Up @@ -73,7 +73,7 @@ python_error::python_error() {
}

python_error::~python_error() {
if (m_type) {
if (m_type && detail::is_alive()) {
gil_scoped_acquire acq;
/* With GIL held */ {
// Clear error status in case the following executes Python code
Expand Down
6 changes: 5 additions & 1 deletion src/nb_ndarray.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ static PyObject *dlpack_from_buffer_protocol(PyObject *o, bool ro) {
}

mt->deleter = [](managed_dltensor *mt2) {
if(! is_alive())
return;
gil_scoped_acquire guard;
Py_buffer *buf = (Py_buffer *) mt2->manager_ctx;
PyBuffer_Release(buf);
Expand Down Expand Up @@ -617,7 +619,7 @@ void ndarray_dec_ref(ndarray_handle *th) noexcept {

if (rc_value == 0) {
check(false, "ndarray_dec_ref(): reference count became negative!");
} else if (rc_value == 1) {
} else if (rc_value == 1 && is_alive()) {
gil_scoped_acquire guard;

Py_XDECREF(th->owner);
Expand Down Expand Up @@ -662,6 +664,8 @@ ndarray_handle *ndarray_create(void *value, size_t ndim, const size_t *shape_in,
scoped_pymalloc<int64_t> shape(ndim), strides(ndim);

auto deleter = [](managed_dltensor *mt) {
if (! is_alive())
return;
gil_scoped_acquire guard;
ndarray_handle *th = (ndarray_handle *) mt->manager_ctx;
ndarray_dec_ref(th);
Expand Down