[3.13] gh-118789: Add PyUnstable_Object_ClearWeakRefsNoCallbacks (GH-118807) (#120695)

This exposes `PyUnstable_Object_ClearWeakRefsNoCallbacks` as an unstable
C-API function to provide a thread-safe mechanism for clearing weakrefs
without executing callbacks.

Some C-API extensions need to clear weakrefs without calling callbacks,
such as after running finalizers like we do in subtype_dealloc.
Previously they could use `_PyWeakref_ClearRef` on each weakref, but
that's not thread-safe in the free-threaded build.

(cherry picked from commit e8752d7b80)

Co-authored-by: Sam Gross <colesbury@gmail.com>
Co-authored-by: Petr Viktorin <encukou@gmail.com>
This commit is contained in:
Miss Islington (bot) 2024-06-18 16:54:51 +02:00 committed by GitHub
parent 4f4973d740
commit 1ce5984961
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 68 additions and 4 deletions

View file

@ -1016,7 +1016,7 @@ PyObject_ClearWeakRefs(PyObject *object)
PyObject *exc = PyErr_GetRaisedException();
PyObject *tuple = PyTuple_New(num_weakrefs * 2);
if (tuple == NULL) {
_PyWeakref_ClearWeakRefsExceptCallbacks(object);
_PyWeakref_ClearWeakRefsNoCallbacks(object);
PyErr_WriteUnraisable(NULL);
PyErr_SetRaisedException(exc);
return;
@ -1057,6 +1057,14 @@ PyObject_ClearWeakRefs(PyObject *object)
PyErr_SetRaisedException(exc);
}
void
PyUnstable_Object_ClearWeakRefsNoCallbacks(PyObject *obj)
{
if (_PyType_SUPPORTS_WEAKREFS(Py_TYPE(obj))) {
_PyWeakref_ClearWeakRefsNoCallbacks(obj);
}
}
/* This function is called by _PyStaticType_Dealloc() to clear weak references.
*
* This is called at the end of runtime finalization, so we can just
@ -1076,7 +1084,7 @@ _PyStaticType_ClearWeakRefs(PyInterpreterState *interp, PyTypeObject *type)
}
void
_PyWeakref_ClearWeakRefsExceptCallbacks(PyObject *obj)
_PyWeakref_ClearWeakRefsNoCallbacks(PyObject *obj)
{
/* Modeled after GET_WEAKREFS_LISTPTR().