[3.14] gh-140061: Use _PyObject_IsUniquelyReferenced() to check if objects are uniquely referenced (gh-140062) (gh-140157)

The previous `Py_REFCNT(x) == 1` checks can have data races in the free
threaded build. `_PyObject_IsUniquelyReferenced(x)` is a more conservative
check that is safe in the free threaded build and is identical to
`Py_REFCNT(x) == 1` in the default GIL-enabled build.
(cherry picked from commit 32c264982e)

Co-authored-by: Sergey Miryanov <sergey.miryanov@gmail.com>
This commit is contained in:
Miss Islington (bot) 2025-10-15 16:49:17 +02:00 committed by GitHub
parent 6b94c7ceeb
commit 045e34964a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 29 additions and 36 deletions

View file

@ -2428,7 +2428,7 @@ set_init(PyObject *so, PyObject *args, PyObject *kwds)
if (!PyArg_UnpackTuple(args, Py_TYPE(self)->tp_name, 0, 1, &iterable))
return -1;
if (Py_REFCNT(self) == 1 && self->fill == 0) {
if (_PyObject_IsUniquelyReferenced((PyObject *)self) && self->fill == 0) {
self->hash = -1;
if (iterable == NULL) {
return 0;
@ -2758,7 +2758,7 @@ int
PySet_Add(PyObject *anyset, PyObject *key)
{
if (!PySet_Check(anyset) &&
(!PyFrozenSet_Check(anyset) || Py_REFCNT(anyset) != 1)) {
(!PyFrozenSet_Check(anyset) || !_PyObject_IsUniquelyReferenced(anyset))) {
PyErr_BadInternalCall();
return -1;
}