gh-125221: Fix free-threading data race in `object.__reduce_ex__` (#125267)

This commit is contained in:
Sam Gross 2024-10-11 03:56:01 -04:00 committed by GitHub
parent c1913effee
commit b12e99261e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 15 additions and 15 deletions

View File

@ -0,0 +1,2 @@
Fix possible race condition when calling :meth:`~object.__reduce_ex__` for the
first time in the free threading build.

View File

@ -2372,6 +2372,14 @@ _PyTypes_InitTypes(PyInterpreterState *interp)
} }
} }
// Cache __reduce__ from PyBaseObject_Type object
PyObject *baseobj_dict = _PyType_GetDict(&PyBaseObject_Type);
PyObject *baseobj_reduce = PyDict_GetItemWithError(baseobj_dict, &_Py_ID(__reduce__));
if (baseobj_reduce == NULL && PyErr_Occurred()) {
return _PyStatus_ERR("Can't get __reduce__ from base object");
}
_Py_INTERP_CACHED_OBJECT(interp, objreduce) = baseobj_reduce;
// Must be after static types are initialized // Must be after static types are initialized
if (_Py_initialize_generic(interp) < 0) { if (_Py_initialize_generic(interp) < 0) {
return _PyStatus_ERR("Can't initialize generic types"); return _PyStatus_ERR("Can't initialize generic types");

View File

@ -7359,18 +7359,7 @@ static PyObject *
object___reduce_ex___impl(PyObject *self, int protocol) object___reduce_ex___impl(PyObject *self, int protocol)
/*[clinic end generated code: output=2e157766f6b50094 input=f326b43fb8a4c5ff]*/ /*[clinic end generated code: output=2e157766f6b50094 input=f326b43fb8a4c5ff]*/
{ {
#define objreduce \ PyObject *reduce;
(_Py_INTERP_CACHED_OBJECT(_PyInterpreterState_GET(), objreduce))
PyObject *reduce, *res;
if (objreduce == NULL) {
PyObject *dict = lookup_tp_dict(&PyBaseObject_Type);
objreduce = PyDict_GetItemWithError(dict, &_Py_ID(__reduce__));
if (objreduce == NULL && PyErr_Occurred()) {
return NULL;
}
}
if (PyObject_GetOptionalAttr(self, &_Py_ID(__reduce__), &reduce) < 0) { if (PyObject_GetOptionalAttr(self, &_Py_ID(__reduce__), &reduce) < 0) {
return NULL; return NULL;
} }
@ -7384,10 +7373,12 @@ object___reduce_ex___impl(PyObject *self, int protocol)
Py_DECREF(reduce); Py_DECREF(reduce);
return NULL; return NULL;
} }
override = (clsreduce != objreduce);
PyInterpreterState *interp = _PyInterpreterState_GET();
override = (clsreduce != _Py_INTERP_CACHED_OBJECT(interp, objreduce));
Py_DECREF(clsreduce); Py_DECREF(clsreduce);
if (override) { if (override) {
res = _PyObject_CallNoArgs(reduce); PyObject *res = _PyObject_CallNoArgs(reduce);
Py_DECREF(reduce); Py_DECREF(reduce);
return res; return res;
} }
@ -7396,7 +7387,6 @@ object___reduce_ex___impl(PyObject *self, int protocol)
} }
return _common_reduce(self, protocol); return _common_reduce(self, protocol);
#undef objreduce
} }
static PyObject * static PyObject *