https://github.com/python/cpython/commit/487e91c1203d635c2871541a544a0e6269e50897
commit: 487e91c1203d635c2871541a544a0e6269e50897
branch: main
author: Kumar Aditya <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2025-12-22T21:45:28+05:30
summary:
gh-129069: fix more thread safety issues in `list` (#143019)
files:
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 44c0ac74e02aa3..27ddc9c2d26dfb 100644
--- a/Lib/test/test_free_threading/test_list.py
+++ b/Lib/test/test_free_threading/test_list.py
@@ -91,6 +91,64 @@ def copy_back_and_forth(b, l):
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()
diff --git a/Objects/listobject.c b/Objects/listobject.c
index f67d1a45a494cb..4a98c8e54ab03f 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -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++) {
_______________________________________________
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]