Skip to content

Commit b12e992

Browse files
authored
gh-125221: Fix free-threading data race in object.__reduce_ex__ (#125267)
1 parent c1913ef commit b12e992

File tree

3 files changed

+15
-15
lines changed

3 files changed

+15
-15
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix possible race condition when calling :meth:`~object.__reduce_ex__` for the
2+
first time in the free threading build.

Objects/object.c

+8
Original file line numberDiff line numberDiff line change
@@ -2372,6 +2372,14 @@ _PyTypes_InitTypes(PyInterpreterState *interp)
23722372
}
23732373
}
23742374

2375+
// Cache __reduce__ from PyBaseObject_Type object
2376+
PyObject *baseobj_dict = _PyType_GetDict(&PyBaseObject_Type);
2377+
PyObject *baseobj_reduce = PyDict_GetItemWithError(baseobj_dict, &_Py_ID(__reduce__));
2378+
if (baseobj_reduce == NULL && PyErr_Occurred()) {
2379+
return _PyStatus_ERR("Can't get __reduce__ from base object");
2380+
}
2381+
_Py_INTERP_CACHED_OBJECT(interp, objreduce) = baseobj_reduce;
2382+
23752383
// Must be after static types are initialized
23762384
if (_Py_initialize_generic(interp) < 0) {
23772385
return _PyStatus_ERR("Can't initialize generic types");

Objects/typeobject.c

+5-15
Original file line numberDiff line numberDiff line change
@@ -7359,18 +7359,7 @@ static PyObject *
73597359
object___reduce_ex___impl(PyObject *self, int protocol)
73607360
/*[clinic end generated code: output=2e157766f6b50094 input=f326b43fb8a4c5ff]*/
73617361
{
7362-
#define objreduce \
7363-
(_Py_INTERP_CACHED_OBJECT(_PyInterpreterState_GET(), objreduce))
7364-
PyObject *reduce, *res;
7365-
7366-
if (objreduce == NULL) {
7367-
PyObject *dict = lookup_tp_dict(&PyBaseObject_Type);
7368-
objreduce = PyDict_GetItemWithError(dict, &_Py_ID(__reduce__));
7369-
if (objreduce == NULL && PyErr_Occurred()) {
7370-
return NULL;
7371-
}
7372-
}
7373-
7362+
PyObject *reduce;
73747363
if (PyObject_GetOptionalAttr(self, &_Py_ID(__reduce__), &reduce) < 0) {
73757364
return NULL;
73767365
}
@@ -7384,10 +7373,12 @@ object___reduce_ex___impl(PyObject *self, int protocol)
73847373
Py_DECREF(reduce);
73857374
return NULL;
73867375
}
7387-
override = (clsreduce != objreduce);
7376+
7377+
PyInterpreterState *interp = _PyInterpreterState_GET();
7378+
override = (clsreduce != _Py_INTERP_CACHED_OBJECT(interp, objreduce));
73887379
Py_DECREF(clsreduce);
73897380
if (override) {
7390-
res = _PyObject_CallNoArgs(reduce);
7381+
PyObject *res = _PyObject_CallNoArgs(reduce);
73917382
Py_DECREF(reduce);
73927383
return res;
73937384
}
@@ -7396,7 +7387,6 @@ object___reduce_ex___impl(PyObject *self, int protocol)
73967387
}
73977388

73987389
return _common_reduce(self, protocol);
7399-
#undef objreduce
74007390
}
74017391

74027392
static PyObject *

0 commit comments

Comments
 (0)