Skip to content

Commit bf397e2

Browse files
[3.14] gh-133467: fix data race in type_set_name (GH-137302) (#137303)
gh-133467: fix data race in `type_set_name` (GH-137302) Fix data race in `type_set_name` by assigning name under stop the world pause making it thread safe in free-threading. (cherry picked from commit e99bc7f) Co-authored-by: Kumar Aditya <[email protected]>
1 parent 070993b commit bf397e2

File tree

3 files changed

+22
-4
lines changed

3 files changed

+22
-4
lines changed

Lib/test/test_free_threading/test_type.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,20 @@ class ClassB(Base):
127127
obj.__class__ = ClassB
128128

129129

130+
def test_name_change(self):
131+
class Foo:
132+
pass
133+
134+
def writer():
135+
for _ in range(1000):
136+
Foo.__name__ = 'Bar'
137+
138+
def reader():
139+
for _ in range(1000):
140+
Foo.__name__
141+
142+
self.run_one(writer, reader)
143+
130144
def run_one(self, writer_func, reader_func):
131145
barrier = threading.Barrier(NTHREADS)
132146

Objects/typeobject.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1434,9 +1434,13 @@ type_set_name(PyObject *tp, PyObject *value, void *Py_UNUSED(closure))
14341434
return -1;
14351435
}
14361436

1437+
PyInterpreterState *interp = _PyInterpreterState_GET();
1438+
_PyEval_StopTheWorld(interp);
14371439
type->tp_name = tp_name;
1438-
Py_SETREF(((PyHeapTypeObject*)type)->ht_name, Py_NewRef(value));
1439-
1440+
PyObject *old_name = ((PyHeapTypeObject*)type)->ht_name;
1441+
((PyHeapTypeObject*)type)->ht_name = Py_NewRef(value);
1442+
_PyEval_StartTheWorld(interp);
1443+
Py_DECREF(old_name);
14401444
return 0;
14411445
}
14421446

@@ -10406,9 +10410,11 @@ slot_tp_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1040610410

1040710411
get = _PyType_LookupRef(tp, &_Py_ID(__get__));
1040810412
if (get == NULL) {
10413+
#ifndef Py_GIL_DISABLED
1040910414
/* Avoid further slowdowns */
1041010415
if (tp->tp_descr_get == slot_tp_descr_get)
1041110416
tp->tp_descr_get = NULL;
10417+
#endif
1041210418
return Py_NewRef(self);
1041310419
}
1041410420
if (obj == NULL)

Tools/tsan/suppressions_free_threading.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,5 @@ race:PyObject_Realloc
5050

5151
# gh-133467. Some of these could be hard to trigger.
5252
race_top:update_one_slot
53-
race_top:slot_tp_descr_get
54-
race_top:type_set_name
5553
race_top:set_tp_bases
5654
race_top:type_set_bases_unlocked

0 commit comments

Comments
 (0)