]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-130920: Fix data race in STORE_SUBSCR_LIST_INT (#130923)
authorSam Gross <colesbury@gmail.com>
Thu, 6 Mar 2025 20:59:48 +0000 (15:59 -0500)
committerGitHub <noreply@github.com>
Thu, 6 Mar 2025 20:59:48 +0000 (15:59 -0500)
The write of the item to the list needs to use an atomic operation in
the free threading build.

Co-authored-by: Tomasz Pytel <tompytel@gmail.com>
Lib/test/test_free_threading/test_list.py
Python/bytecodes.c
Python/executor_cases.c.h
Python/generated_cases.c.h

index a705161369e8dd99233a166a57597c2f7bfafd0d..2c9af65273a1c8636210364d6066f1f53fdf2cb7 100644 (file)
@@ -1,6 +1,6 @@
 import unittest
 
-from threading import Thread
+from threading import Thread, Barrier
 from unittest import TestCase
 
 from test.support import threading_helper
@@ -71,6 +71,20 @@ class TestList(TestCase):
         for reader in readers:
             reader.join()
 
+    def test_store_list_int(self):
+        def copy_back_and_forth(b, l):
+            b.wait()
+            for _ in range(100):
+                l[0] = l[1]
+                l[1] = l[0]
+
+        l = [0, 1]
+        barrier = Barrier(NTHREAD)
+        threads = [Thread(target=copy_back_and_forth, args=(barrier, l))
+                   for _ in range(NTHREAD)]
+        with threading_helper.start_threads(threads):
+            pass
+
 
 if __name__ == "__main__":
     unittest.main()
index 24aa7bbb87c193357cc29bb6e51b4d5d9c34e486..718c8f5607c55b9d31c23e558c35da817a13b292 100644 (file)
@@ -1015,7 +1015,8 @@ dummy_func(
             STAT_INC(STORE_SUBSCR, hit);
 
             PyObject *old_value = PyList_GET_ITEM(list, index);
-            PyList_SET_ITEM(list, index, PyStackRef_AsPyObjectSteal(value));
+            FT_ATOMIC_STORE_PTR_RELEASE(_PyList_ITEMS(list)[index],
+                                        PyStackRef_AsPyObjectSteal(value));
             assert(old_value != NULL);
             UNLOCK_OBJECT(list);  // unlock before decrefs!
             PyStackRef_CLOSE_SPECIALIZED(sub_st, _PyLong_ExactDealloc);
index 29160b9f6634c54bccbd2f2d7bdbcd7d45b4c786..94f05c620890566aa9c44264a1fbd6933822ebe5 100644 (file)
             }
             STAT_INC(STORE_SUBSCR, hit);
             PyObject *old_value = PyList_GET_ITEM(list, index);
-            PyList_SET_ITEM(list, index, PyStackRef_AsPyObjectSteal(value));
+            FT_ATOMIC_STORE_PTR_RELEASE(_PyList_ITEMS(list)[index],
+                                        PyStackRef_AsPyObjectSteal(value));
             assert(old_value != NULL);
             UNLOCK_OBJECT(list);  // unlock before decrefs!
             PyStackRef_CLOSE_SPECIALIZED(sub_st, _PyLong_ExactDealloc);
index 5216918560a48783e3017a428aa4f4908165c89f..33d00afea18e1ced7818966ccda3e93fc7796b77 100644 (file)
             }
             STAT_INC(STORE_SUBSCR, hit);
             PyObject *old_value = PyList_GET_ITEM(list, index);
-            PyList_SET_ITEM(list, index, PyStackRef_AsPyObjectSteal(value));
+            FT_ATOMIC_STORE_PTR_RELEASE(_PyList_ITEMS(list)[index],
+                                        PyStackRef_AsPyObjectSteal(value));
             assert(old_value != NULL);
             UNLOCK_OBJECT(list);  // unlock before decrefs!
             PyStackRef_CLOSE_SPECIALIZED(sub_st, _PyLong_ExactDealloc);