From ebd98bd8ed0dc7e689b84d76e673363b4bae1895 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 8 Jul 2026 13:23:43 +0300 Subject: [PATCH 1/2] gh-153298: Fix data race in `GenericAlias` parameter initialization on FT --- Lib/test/test_free_threading/test_types.py | 34 +++++++++++++++++++ ...-07-08-13-23-11.gh-issue-153298.wvcXxN.rst | 2 ++ Objects/genericaliasobject.c | 12 ++++++- 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 Lib/test/test_free_threading/test_types.py create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-07-08-13-23-11.gh-issue-153298.wvcXxN.rst diff --git a/Lib/test/test_free_threading/test_types.py b/Lib/test/test_free_threading/test_types.py new file mode 100644 index 000000000000000..84375515168fdce --- /dev/null +++ b/Lib/test/test_free_threading/test_types.py @@ -0,0 +1,34 @@ +import unittest +import types +from typing import TypeVar +from test.support import threading_helper + +threading_helper.requires_working_threading(module=True) + + +class TestGenericAlias(unittest.TestCase): + def test_repr_race(self): + # gh-153298 + + T = TypeVar('T') + slot = [list[T]] + + def access(): + for _ in range(2000): + try: + _ = slot[0].__parameters__ + except Exception: + pass + + def refresh(): + for _ in range(2000): + slot[0] = list[T] + + threading_helper.run_concurrently([ + *[access for _ in range(6)], + *[refresh for _ in range(2)], + ]) + + +if __name__ == "__main__": + unittest.main() diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-07-08-13-23-11.gh-issue-153298.wvcXxN.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-08-13-23-11.gh-issue-153298.wvcXxN.rst new file mode 100644 index 000000000000000..38d548834d5e02e --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-08-13-23-11.gh-issue-153298.wvcXxN.rst @@ -0,0 +1,2 @@ +Fixes a data race in :class:`types.GenericAlias` ``__parameters__`` +initialization on free-threading builds. diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c index c2083e6fcb77f47..4e85927def7ea78 100644 --- a/Objects/genericaliasobject.c +++ b/Objects/genericaliasobject.c @@ -841,7 +841,7 @@ static PyMemberDef ga_members[] = { }; static PyObject * -ga_parameters(PyObject *self, void *unused) +ga_parameters_lock_held(PyObject *self) { gaobject *alias = (gaobject *)self; if (alias->parameters == NULL) { @@ -853,6 +853,16 @@ ga_parameters(PyObject *self, void *unused) return Py_NewRef(alias->parameters); } +static PyObject * +ga_parameters(PyObject *self, void *unused) +{ + PyObject *result; + Py_BEGIN_CRITICAL_SECTION(self); + result = ga_parameters_lock_held(self); + Py_END_CRITICAL_SECTION(); + return result; +} + static PyObject * ga_unpacked_tuple_args(PyObject *self, void *unused) { From 059d1f5a9793519842fa4c139ac8f211d1f4cd5b Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 8 Jul 2026 13:37:22 +0300 Subject: [PATCH 2/2] fix ci --- Lib/test/test_free_threading/test_types.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Lib/test/test_free_threading/test_types.py b/Lib/test/test_free_threading/test_types.py index 84375515168fdce..76fcf1590122f54 100644 --- a/Lib/test/test_free_threading/test_types.py +++ b/Lib/test/test_free_threading/test_types.py @@ -1,5 +1,4 @@ import unittest -import types from typing import TypeVar from test.support import threading_helper @@ -7,7 +6,7 @@ class TestGenericAlias(unittest.TestCase): - def test_repr_race(self): + def test_parameters_race(self): # gh-153298 T = TypeVar('T')