]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-129069: fix more thread safety issues in `list` (#143019)
authorKumar Aditya <kumaraditya@python.org>
Mon, 22 Dec 2025 16:15:28 +0000 (21:45 +0530)
committerGitHub <noreply@github.com>
Mon, 22 Dec 2025 16:15:28 +0000 (21:45 +0530)
Lib/test/test_free_threading/test_list.py
Objects/listobject.c

index 44c0ac74e02aa35f096736c9f4a073c5fce55c54..27ddc9c2d26dfbc3e992ad57466e11a2baf1e9e6 100644 (file)
@@ -91,6 +91,64 @@ class TestList(TestCase):
         with threading_helper.start_threads(threads):
             pass
 
+    def test_reverse(self):
+        def reverse_list(b, l):
+            b.wait()
+            for _ in range(100):
+                l.reverse()
+
+        def reader_list(b, l):
+            b.wait()
+            for _ in range(100):
+                for i in range(10):
+                    self.assertTrue(0 <= l[i] < 10)
+
+        l = list(range(10))
+        barrier = Barrier(2)
+        threads = [Thread(target=reverse_list, args=(barrier, l)),
+                   Thread(target=reader_list, args=(barrier, l))]
+        with threading_helper.start_threads(threads):
+            pass
+
+    def test_slice_assignment1(self):
+        def assign_slice(b, l):
+            b.wait()
+            for _ in range(100):
+                l[2:5] = [7, 8, 9]
+
+        def reader_list(b, l):
+            b.wait()
+            for _ in range(100):
+                self.assertIn(l[2], (2, 7))
+                self.assertIn(l[3], (3, 8))
+                self.assertIn(l[4], (4, 9))
+
+        l = list(range(10))
+        barrier = Barrier(2)
+        threads = [Thread(target=assign_slice, args=(barrier, l)),
+                   Thread(target=reader_list, args=(barrier, l))]
+        with threading_helper.start_threads(threads):
+            pass
+
+    def test_slice_assignment2(self):
+        def assign_slice(b, l):
+            b.wait()
+            for _ in range(100):
+                l[::2] = [10, 11, 12, 13, 14]
+
+        def reader_list(b, l):
+            b.wait()
+            for _ in range(100):
+                for i in range(0, 10, 2):
+                    self.assertIn(l[i], (i, 10 + i // 2))
+
+        l = list(range(10))
+        barrier = Barrier(2)
+        threads = [Thread(target=assign_slice, args=(barrier, l)),
+                   Thread(target=reader_list, args=(barrier, l))]
+        with threading_helper.start_threads(threads):
+            pass
+
 
 if __name__ == "__main__":
     unittest.main()
index f67d1a45a494cbd6dfc37149f1e4ab412032d554..4a98c8e54ab03fe464471265d9bf6539b6c29739 100644 (file)
@@ -501,7 +501,7 @@ ins1(PyListObject *self, Py_ssize_t where, PyObject *v)
         where = n;
     items = self->ob_item;
     for (i = n; --i >= where; )
-        FT_ATOMIC_STORE_PTR_RELAXED(items[i+1], items[i]);
+        FT_ATOMIC_STORE_PTR_RELEASE(items[i+1], items[i]);
     FT_ATOMIC_STORE_PTR_RELEASE(items[where], Py_NewRef(v));
     return 0;
 }
@@ -1122,7 +1122,7 @@ list_ass_item_lock_held(PyListObject *a, Py_ssize_t i, PyObject *v)
     if (v == NULL) {
         Py_ssize_t size = Py_SIZE(a);
         for (Py_ssize_t idx = i; idx < size - 1; idx++) {
-            FT_ATOMIC_STORE_PTR_RELAXED(a->ob_item[idx], a->ob_item[idx + 1]);
+            FT_ATOMIC_STORE_PTR_RELEASE(a->ob_item[idx], a->ob_item[idx + 1]);
         }
         Py_SET_SIZE(a, size - 1);
     }
@@ -1601,8 +1601,8 @@ reverse_slice(PyObject **lo, PyObject **hi)
     --hi;
     while (lo < hi) {
         PyObject *t = *lo;
-        *lo = *hi;
-        *hi = t;
+        FT_ATOMIC_STORE_PTR_RELEASE(*lo, *hi);
+        FT_ATOMIC_STORE_PTR_RELEASE(*hi, t);
         ++lo;
         --hi;
     }
@@ -3845,7 +3845,7 @@ list_ass_subscript_lock_held(PyObject *_self, PyObject *item, PyObject *value)
                  cur += (size_t)step, i++) {
                 garbage[i] = selfitems[cur];
                 ins = Py_NewRef(seqitems[i]);
-                selfitems[cur] = ins;
+                FT_ATOMIC_STORE_PTR_RELEASE(selfitems[cur], ins);
             }
 
             for (i = 0; i < slicelength; i++) {