Skip to content

Commit 9e08023

Browse files
gh-145036: Fix data race for list capacity in free-threading (#145365)
Co-authored-by: Kumar Aditya <kumaraditya@python.org>
1 parent 3f33bf8 commit 9e08023

File tree

3 files changed

+30
-2
lines changed

3 files changed

+30
-2
lines changed

Lib/test/test_free_threading/test_list.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,27 @@ def reader_list(b, l):
149149
with threading_helper.start_threads(threads):
150150
pass
151151

152+
# gh-145036: race condition with list.__sizeof__()
153+
def test_list_sizeof_free_threaded_build(self):
154+
L = []
155+
156+
def mutate_function():
157+
for _ in range(100):
158+
L.append(1)
159+
L.pop()
160+
161+
def size_function():
162+
for _ in range(100):
163+
L.__sizeof__()
164+
165+
threads = []
166+
for _ in range(4):
167+
threads.append(Thread(target=mutate_function))
168+
threads.append(Thread(target=size_function))
169+
170+
with threading_helper.start_threads(threads):
171+
pass
172+
152173

153174
if __name__ == "__main__":
154175
unittest.main()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
In free-threaded build, fix race condition when calling :meth:`!__sizeof__` on a :class:`list`

Objects/listobject.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3582,8 +3582,14 @@ list___sizeof___impl(PyListObject *self)
35823582
/*[clinic end generated code: output=3417541f95f9a53e input=b8030a5d5ce8a187]*/
35833583
{
35843584
size_t res = _PyObject_SIZE(Py_TYPE(self));
3585-
Py_ssize_t allocated = FT_ATOMIC_LOAD_SSIZE_RELAXED(self->allocated);
3586-
res += (size_t)allocated * sizeof(void*);
3585+
#ifdef Py_GIL_DISABLED
3586+
PyObject **ob_item = _Py_atomic_load_ptr(&self->ob_item);
3587+
if (ob_item != NULL) {
3588+
res += list_capacity(ob_item) * sizeof(PyObject *);
3589+
}
3590+
#else
3591+
res += (size_t)self->allocated * sizeof(PyObject *);
3592+
#endif
35873593
return PyLong_FromSize_t(res);
35883594
}
35893595

0 commit comments

Comments
 (0)