https://github.com/python/cpython/commit/9e0802330caca51fed7fc0c8c1dcce2daf03d8bd
commit: 9e0802330caca51fed7fc0c8c1dcce2daf03d8bd
branch: main
author: bkap123 <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2026-03-10T22:00:11+05:30
summary:

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

Co-authored-by: Kumar Aditya <[email protected]>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-18-42-36.gh-issue-145036.70Kbfz.rst
M Lib/test/test_free_threading/test_list.py
M Objects/listobject.c

diff --git a/Lib/test/test_free_threading/test_list.py 
b/Lib/test/test_free_threading/test_list.py
index 27ddc9c2d26dfb..0ede4df103f728 100644
--- a/Lib/test/test_free_threading/test_list.py
+++ b/Lib/test/test_free_threading/test_list.py
@@ -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()
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-18-42-36.gh-issue-145036.70Kbfz.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-18-42-36.gh-issue-145036.70Kbfz.rst
new file mode 100644
index 00000000000000..2a565c1d02bc2e
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-28-18-42-36.gh-issue-145036.70Kbfz.rst
@@ -0,0 +1 @@
+In free-threaded build, fix race condition when calling :meth:`!__sizeof__` on 
a :class:`list`
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 7fc21907fefd31..62d04ab150a77a 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -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);
 }
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to