Skip to content

Commit

Permalink
check GIL when performing reference counting operations in debug mode
Browse files Browse the repository at this point in the history
  • Loading branch information
wjakob committed Dec 9, 2022
1 parent ee35767 commit a1b245f
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 2 deletions.
8 changes: 8 additions & 0 deletions include/nanobind/nb_lib.h
Expand Up @@ -398,5 +398,13 @@ NB_CORE bool load_u64(PyObject *o, uint8_t flags, uint64_t *out) noexcept;
NB_CORE bool load_f32(PyObject *o, uint8_t flags, float *out) noexcept;
NB_CORE bool load_f64(PyObject *o, uint8_t flags, double *out) noexcept;

// ========================================================================

/// Increase the reference count of 'o', and check that the GIL is held
NB_CORE void incref_checked(PyObject *o) noexcept;

/// Decrease the reference count of 'o', and check that the GIL is held
NB_CORE void decref_checked(PyObject *o) noexcept;

NAMESPACE_END(detail)
NAMESPACE_END(NB_NAMESPACE)
19 changes: 17 additions & 2 deletions include/nanobind/nb_types.h
Expand Up @@ -156,8 +156,23 @@ class handle : public detail::api<handle> {
NB_INLINE handle(const PyObject *ptr) : m_ptr((PyObject *) ptr) { }
NB_INLINE handle(const PyTypeObject *ptr) : m_ptr((PyObject *) ptr) { }

const handle& inc_ref() const & noexcept { Py_XINCREF(m_ptr); return *this; }
const handle& dec_ref() const & noexcept { Py_XDECREF(m_ptr); return *this; }
const handle& inc_ref() const & noexcept {
#if defined(NDEBUG)
Py_XINCREF(m_ptr);
#else
detail::incref_checked(m_ptr);
#endif
return *this;
}

const handle& dec_ref() const & noexcept {
#if defined(NDEBUG)
Py_XDECREF(m_ptr);
#else
detail::decref_checked(m_ptr);
#endif
return *this;
}

NB_INLINE operator bool() const { return m_ptr != nullptr; }
NB_INLINE PyObject *ptr() const { return m_ptr; }
Expand Down
21 changes: 21 additions & 0 deletions src/common.cpp
Expand Up @@ -865,5 +865,26 @@ bool load_i64(PyObject *o, uint8_t flags, int64_t *out) noexcept {
return load_int(o, flags, out);
}


// ========================================================================

void incref_checked(PyObject *o) noexcept {
if (!o)
return;
if (!PyGILState_Check())
fail("nanobind::detail::incref_check(): attempted to change the "
"reference count of a Python object while the GIL was not held.");
Py_INCREF(o);
}

void decref_checked(PyObject *o) noexcept {
if (!o)
return;
if (!PyGILState_Check())
fail("nanobind::detail::decref_check(): attempted to change the "
"reference count of a Python object while the GIL was not held.");
Py_DECREF(o);
}

NAMESPACE_END(detail)
NAMESPACE_END(NB_NAMESPACE)

0 comments on commit a1b245f

Please sign in to comment.