gh-130920: Fix data race in STORE_SUBSCR_LIST_INT (#130923)

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>
This commit is contained in:
Sam Gross 2025-03-06 15:59:48 -05:00 committed by GitHub
parent 6c6600f683
commit a025f27d94
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 21 additions and 4 deletions

View 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()

View 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);

View file

@ -1522,7 +1522,8 @@
}
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);

View file

@ -11259,7 +11259,8 @@
}
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);