gh-118362: Fix thread safety around lookups from the type cache in the face of concurrent mutators (#118454)

Add _PyType_LookupRef and use incref before setting attribute on type
Makes setting an attribute on a class and signaling type modified atomic
Avoid adding re-entrancy exposing the type cache in an inconsistent state by decrefing after type is updated
This commit is contained in:
Dino Viehland 2024-05-06 10:50:35 -07:00 committed by GitHub
parent e6b213ee3f
commit 5a1618a2c8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 439 additions and 126 deletions

View file

@ -188,15 +188,18 @@ method_getattro(PyObject *obj, PyObject *name)
if (PyType_Ready(tp) < 0)
return NULL;
}
descr = _PyType_Lookup(tp, name);
descr = _PyType_LookupRef(tp, name);
}
if (descr != NULL) {
descrgetfunc f = TP_DESCR_GET(Py_TYPE(descr));
if (f != NULL)
return f(descr, obj, (PyObject *)Py_TYPE(obj));
if (f != NULL) {
PyObject *res = f(descr, obj, (PyObject *)Py_TYPE(obj));
Py_DECREF(descr);
return res;
}
else {
return Py_NewRef(descr);
return descr;
}
}
@ -410,14 +413,17 @@ instancemethod_getattro(PyObject *self, PyObject *name)
if (PyType_Ready(tp) < 0)
return NULL;
}
descr = _PyType_Lookup(tp, name);
descr = _PyType_LookupRef(tp, name);
if (descr != NULL) {
descrgetfunc f = TP_DESCR_GET(Py_TYPE(descr));
if (f != NULL)
return f(descr, self, (PyObject *)Py_TYPE(self));
if (f != NULL) {
PyObject *res = f(descr, self, (PyObject *)Py_TYPE(self));
Py_DECREF(descr);
return res;
}
else {
return Py_NewRef(descr);
return descr;
}
}