Skip to content

Commit cabb466

Browse files
committed
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.
1 parent 97402f7 commit cabb466

File tree

3 files changed

+35
-8
lines changed

3 files changed

+35
-8
lines changed

src/dict.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,16 @@ object dict_base::get(object_cref k) const
6868
{
6969
if (check_exact(this))
7070
{
71+
#ifdef Py_GIL_DISABLED
72+
PyObject* result;
73+
if (PyDict_GetItemRef(this->ptr(),k.ptr(),&result) < 0) {
74+
throw_error_already_set();
75+
}
76+
return object(detail::new_reference(result ? result : Py_None));
77+
#else
7178
PyObject* result = PyDict_GetItem(this->ptr(),k.ptr());
7279
return object(detail::borrowed_reference(result ? result : Py_None));
80+
#endif
7381
}
7482
else
7583
{

src/object/function_doc_signature.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,15 @@ namespace boost { namespace python { namespace objects {
135135
str name(get_qualname(py_type));
136136
if ( py_type->tp_flags & Py_TPFLAGS_HEAPTYPE ) {
137137
// Qualify the type name if it is defined in a different module.
138-
PyObject *type_module_name = PyDict_GetItemString(py_type->tp_dict, "__module__");
138+
PyObject *type_module_name;
139+
#if PY_VERSION_HEX >= 0x030D0000
140+
if (PyDict_GetItemStringRef(py_type->tp_dict, "__module__", &type_module_name) < 0) {
141+
throw_error_already_set();
142+
}
143+
#else
144+
type_module_name = PyDict_GetItemString(py_type->tp_dict, "__module__");
145+
Py_XINCREF(type_module_name);
146+
#endif
139147
if (
140148
type_module_name
141149
&& PyObject_RichCompareBool(
@@ -144,8 +152,11 @@ namespace boost { namespace python { namespace objects {
144152
Py_NE
145153
) != 0
146154
) {
147-
return str("%s.%s" % make_tuple(handle<>(borrowed(type_module_name)), name));
155+
str result = str("%s.%s" % make_tuple(handle<>(type_module_name), name));
156+
return result;
148157
}
158+
// Clean up the strong reference if we didn't use it
159+
Py_XDECREF(type_module_name);
149160
}
150161
return name;
151162
} else {

src/wrapper.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,28 @@ namespace detail
2121
this->m_self, const_cast<char*>(name))))
2222
)
2323
{
24-
PyObject* borrowed_f = 0;
25-
24+
PyObject* class_f = 0;
25+
2626
if (
2727
PyMethod_Check(m.get())
2828
&& PyMethod_GET_SELF(m.get()) == this->m_self
2929
&& class_object->tp_dict != 0
3030
)
3131
{
32-
borrowed_f = ::PyDict_GetItemString(
32+
#if PY_VERSION_HEX >= 0x030D0000
33+
if (::PyDict_GetItemStringRef(
34+
class_object->tp_dict, const_cast<char*>(name), &class_f) < 0) {
35+
throw_error_already_set();
36+
}
37+
#else
38+
class_f = ::PyDict_GetItemString(
3339
class_object->tp_dict, const_cast<char*>(name));
34-
35-
40+
Py_XINCREF(class_f);
41+
#endif
3642
}
37-
if (borrowed_f != PyMethod_GET_FUNCTION(m.get()))
43+
bool is_override = (class_f != PyMethod_GET_FUNCTION(m.get()));
44+
Py_XDECREF(class_f);
45+
if (is_override)
3846
return override(m);
3947
}
4048
}

0 commit comments

Comments
 (0)