Skip to content

Commit 3d8f2aa

Browse files
[3.14] gh-153298: Fix data race in GenericAlias parameter initialization on FT (GH-153318) (#153346)
gh-153298: Fix data race in `GenericAlias` parameter initialization on FT (GH-153318) (cherry picked from commit 68abf17) Co-authored-by: sobolevn <mail@sobolevn.me>
1 parent 5d9e46e commit 3d8f2aa

3 files changed

Lines changed: 46 additions & 1 deletion

File tree

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import unittest
2+
from typing import TypeVar
3+
from test.support import threading_helper
4+
5+
threading_helper.requires_working_threading(module=True)
6+
7+
8+
class TestGenericAlias(unittest.TestCase):
9+
def test_parameters_race(self):
10+
# gh-153298
11+
12+
T = TypeVar('T')
13+
slot = [list[T]]
14+
15+
def access():
16+
for _ in range(2000):
17+
try:
18+
_ = slot[0].__parameters__
19+
except Exception:
20+
pass
21+
22+
def refresh():
23+
for _ in range(2000):
24+
slot[0] = list[T]
25+
26+
threading_helper.run_concurrently([
27+
*[access for _ in range(6)],
28+
*[refresh for _ in range(2)],
29+
])
30+
31+
32+
if __name__ == "__main__":
33+
unittest.main()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fixes a data race in :class:`types.GenericAlias` ``__parameters__``
2+
initialization on free-threading builds.

Objects/genericaliasobject.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,7 @@ static PyMemberDef ga_members[] = {
838838
};
839839

840840
static PyObject *
841-
ga_parameters(PyObject *self, void *unused)
841+
ga_parameters_lock_held(PyObject *self)
842842
{
843843
gaobject *alias = (gaobject *)self;
844844
if (alias->parameters == NULL) {
@@ -850,6 +850,16 @@ ga_parameters(PyObject *self, void *unused)
850850
return Py_NewRef(alias->parameters);
851851
}
852852

853+
static PyObject *
854+
ga_parameters(PyObject *self, void *unused)
855+
{
856+
PyObject *result;
857+
Py_BEGIN_CRITICAL_SECTION(self);
858+
result = ga_parameters_lock_held(self);
859+
Py_END_CRITICAL_SECTION();
860+
return result;
861+
}
862+
853863
static PyObject *
854864
ga_unpacked_tuple_args(PyObject *self, void *unused)
855865
{

0 commit comments

Comments
 (0)