Skip to content

Commit 436d812

Browse files
committed
Move code location
1 parent 7c5d505 commit 436d812

File tree

2 files changed

+27
-28
lines changed

2 files changed

+27
-28
lines changed

include/pybind11/detail/internals.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,7 @@ PYBIND11_NOINLINE internals &get_internals() {
831831
/// Return the PyObject* for the internals capsule (borrowed reference).
832832
/// Returns nullptr if the capsule doesn't exist yet.
833833
/// This is used to prevent use-after-free during interpreter shutdown by allowing pybind11 types
834-
/// to hold a reference to the capsule (see make_new_python_type in class.h).
834+
/// to hold a reference to the capsule (see comments in generic_type::initialize).
835835
inline PyObject *get_internals_capsule() {
836836
auto state_dict = reinterpret_borrow<dict>(get_python_state_dict());
837837
return dict_getitemstring(state_dict.ptr(), PYBIND11_INTERNALS_ID);
@@ -850,7 +850,7 @@ inline const std::string &get_local_internals_key() {
850850
/// Return the PyObject* for the local_internals capsule (borrowed reference).
851851
/// Returns nullptr if the capsule doesn't exist yet.
852852
/// This is used to prevent use-after-free during interpreter shutdown by allowing pybind11 types
853-
/// to hold a reference to the capsule (see make_new_python_type in class.h).
853+
/// to hold a reference to the capsule (see comments in generic_type::initialize).
854854
inline PyObject *get_local_internals_capsule() {
855855
const auto &key = get_local_internals_key();
856856
auto state_dict = reinterpret_borrow<dict>(get_python_state_dict());

include/pybind11/pybind11.h

Lines changed: 25 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1721,32 +1721,6 @@ class generic_type : public object {
17211721
#endif
17221722
}
17231723

1724-
// Prevent use-after-free during interpreter shutdown. GC order is not guaranteed, so
1725-
// the internals capsule may be destroyed (resetting internals via internals_shutdown)
1726-
// before all pybind11 types are destroyed. If a type's tp_traverse/tp_clear then calls
1727-
// py::cast, it would recreate an empty internals and fail because the type registry is
1728-
// gone.
1729-
//
1730-
// By holding references to the capsules, we ensure they outlive all pybind11 types. We
1731-
// use weakrefs on the type with a cpp_function callback. When the type is destroyed,
1732-
// Python will call the callback which releases the capsule reference and the weakref.
1733-
if (PyObject *capsule = get_internals_capsule()) {
1734-
Py_INCREF(capsule);
1735-
(void) weakref(handle(m_ptr), cpp_function([](handle wr) -> void {
1736-
Py_XDECREF(get_internals_capsule());
1737-
wr.dec_ref();
1738-
}))
1739-
.release();
1740-
}
1741-
if (PyObject *capsule = get_local_internals_capsule()) {
1742-
Py_INCREF(capsule);
1743-
(void) weakref(handle(m_ptr), cpp_function([](handle wr) -> void {
1744-
Py_XDECREF(get_local_internals_capsule());
1745-
wr.dec_ref();
1746-
}))
1747-
.release();
1748-
}
1749-
17501724
PYBIND11_WARNING_PUSH
17511725
#if defined(__GNUC__) && __GNUC__ == 12
17521726
// When using GCC 12 these warnings are disabled as they trigger
@@ -1759,6 +1733,31 @@ class generic_type : public object {
17591733
PYBIND11_WARNING_POP
17601734
});
17611735

1736+
// Prevent use-after-free during interpreter shutdown. GC order is not guaranteed, so the
1737+
// internals capsule may be destroyed (resetting internals via internals_shutdown) before
1738+
// all pybind11 types are destroyed. If a type's tp_traverse/tp_clear then calls py::cast,
1739+
// it would recreate an empty internals and fail because the type registry is gone.
1740+
//
1741+
// By holding references to the capsules, we ensure they outlive all pybind11 types. We use
1742+
// weakrefs on the type with a cpp_function callback. When the type is destroyed, Python
1743+
// will call the callback which releases the capsule reference and the weakref.
1744+
if (PyObject *capsule = get_internals_capsule()) {
1745+
Py_INCREF(capsule);
1746+
(void) weakref(handle(m_ptr), cpp_function([](handle wr) -> void {
1747+
Py_XDECREF(get_internals_capsule());
1748+
wr.dec_ref();
1749+
}))
1750+
.release();
1751+
}
1752+
if (PyObject *capsule = get_local_internals_capsule()) {
1753+
Py_INCREF(capsule);
1754+
(void) weakref(handle(m_ptr), cpp_function([](handle wr) -> void {
1755+
Py_XDECREF(get_local_internals_capsule());
1756+
wr.dec_ref();
1757+
}))
1758+
.release();
1759+
}
1760+
17621761
if (rec.bases.size() > 1 || rec.multiple_inheritance) {
17631762
mark_parents_nonsimple(tinfo->type);
17641763
tinfo->simple_ancestors = false;

0 commit comments

Comments
 (0)