gh-145036: Fix data race for list capacity in free-threading (#145365)

Co-authored-by: Kumar Aditya <kumaraditya@python.org>
This commit is contained in:
bkap123 2026-03-10 12:30:11 -04:00 committed by GitHub
parent 3f33bf83e8
commit 9e0802330c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 30 additions and 2 deletions

View file

@ -149,6 +149,27 @@ def reader_list(b, l):
with threading_helper.start_threads(threads):
pass
# gh-145036: race condition with list.__sizeof__()
def test_list_sizeof_free_threaded_build(self):
L = []
def mutate_function():
for _ in range(100):
L.append(1)
L.pop()
def size_function():
for _ in range(100):
L.__sizeof__()
threads = []
for _ in range(4):
threads.append(Thread(target=mutate_function))
threads.append(Thread(target=size_function))
with threading_helper.start_threads(threads):
pass
if __name__ == "__main__":
unittest.main()

View file

@ -0,0 +1 @@
In free-threaded build, fix race condition when calling :meth:`!__sizeof__` on a :class:`list`

View file

@ -3582,8 +3582,14 @@ list___sizeof___impl(PyListObject *self)
/*[clinic end generated code: output=3417541f95f9a53e input=b8030a5d5ce8a187]*/
{
size_t res = _PyObject_SIZE(Py_TYPE(self));
Py_ssize_t allocated = FT_ATOMIC_LOAD_SSIZE_RELAXED(self->allocated);
res += (size_t)allocated * sizeof(void*);
#ifdef Py_GIL_DISABLED
PyObject **ob_item = _Py_atomic_load_ptr(&self->ob_item);
if (ob_item != NULL) {
res += list_capacity(ob_item) * sizeof(PyObject *);
}
#else
res += (size_t)self->allocated * sizeof(PyObject *);
#endif
return PyLong_FromSize_t(res);
}