2
0
mirror of https://github.com/boostorg/python.git synced 2026-01-19 04:22:16 +00:00

Use strong reference APIs.

For the free-threaded build, it is not safe use borrowed references.
Another thread could deallocate the object and cause the reference to
become invalid.  Replace API calls that borrow references with strong
reference APIs.
This commit is contained in:
Neil Schemenauer
2025-10-13 20:59:57 -07:00
parent 97402f7925
commit cabb466057
3 changed files with 35 additions and 8 deletions

View File

@@ -68,8 +68,16 @@ object dict_base::get(object_cref k) const
{
if (check_exact(this))
{
#ifdef Py_GIL_DISABLED
PyObject* result;
if (PyDict_GetItemRef(this->ptr(),k.ptr(),&result) < 0) {
throw_error_already_set();
}
return object(detail::new_reference(result ? result : Py_None));
#else
PyObject* result = PyDict_GetItem(this->ptr(),k.ptr());
return object(detail::borrowed_reference(result ? result : Py_None));
#endif
}
else
{

View File

@@ -135,7 +135,15 @@ namespace boost { namespace python { namespace objects {
str name(get_qualname(py_type));
if ( py_type->tp_flags & Py_TPFLAGS_HEAPTYPE ) {
// Qualify the type name if it is defined in a different module.
PyObject *type_module_name = PyDict_GetItemString(py_type->tp_dict, "__module__");
PyObject *type_module_name;
#if PY_VERSION_HEX >= 0x030D0000
if (PyDict_GetItemStringRef(py_type->tp_dict, "__module__", &type_module_name) < 0) {
throw_error_already_set();
}
#else
type_module_name = PyDict_GetItemString(py_type->tp_dict, "__module__");
Py_XINCREF(type_module_name);
#endif
if (
type_module_name
&& PyObject_RichCompareBool(
@@ -144,8 +152,11 @@ namespace boost { namespace python { namespace objects {
Py_NE
) != 0
) {
return str("%s.%s" % make_tuple(handle<>(borrowed(type_module_name)), name));
str result = str("%s.%s" % make_tuple(handle<>(type_module_name), name));
return result;
}
// Clean up the strong reference if we didn't use it
Py_XDECREF(type_module_name);
}
return name;
} else {

View File

@@ -21,20 +21,28 @@ namespace detail
this->m_self, const_cast<char*>(name))))
)
{
PyObject* borrowed_f = 0;
PyObject* class_f = 0;
if (
PyMethod_Check(m.get())
&& PyMethod_GET_SELF(m.get()) == this->m_self
&& class_object->tp_dict != 0
)
{
borrowed_f = ::PyDict_GetItemString(
#if PY_VERSION_HEX >= 0x030D0000
if (::PyDict_GetItemStringRef(
class_object->tp_dict, const_cast<char*>(name), &class_f) < 0) {
throw_error_already_set();
}
#else
class_f = ::PyDict_GetItemString(
class_object->tp_dict, const_cast<char*>(name));
Py_XINCREF(class_f);
#endif
}
if (borrowed_f != PyMethod_GET_FUNCTION(m.get()))
bool is_override = (class_f != PyMethod_GET_FUNCTION(m.get()));
Py_XDECREF(class_f);
if (is_override)
return override(m);
}
}