Skip to content

Commit e99bc7f

Browse files
gh-133467: fix data race in type_set_name (#137302)
Fix data race in `type_set_name` by assigning name under stop the world pause making it thread safe in free-threading.
1 parent 9ced5c4 commit e99bc7f

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
@@ -1535,9 +1535,13 @@ type_set_name(PyObject *tp, PyObject *value, void *Py_UNUSED(closure))
15351535
return -1;
15361536
}
15371537

1538+
PyInterpreterState *interp = _PyInterpreterState_GET();
1539+
_PyEval_StopTheWorld(interp);
15381540
type->tp_name = tp_name;
1539-
Py_SETREF(((PyHeapTypeObject*)type)->ht_name, Py_NewRef(value));
1540-
1541+
PyObject *old_name = ((PyHeapTypeObject*)type)->ht_name;
1542+
((PyHeapTypeObject*)type)->ht_name = Py_NewRef(value);
1543+
_PyEval_StartTheWorld(interp);
1544+
Py_DECREF(old_name);
15411545
return 0;
15421546
}
15431547

@@ -10706,9 +10710,11 @@ slot_tp_descr_get(PyObject *self, PyObject *obj, PyObject *type)
1070610710

1070710711
get = _PyType_LookupRef(tp, &_Py_ID(__get__));
1070810712
if (get == NULL) {
10713+
#ifndef Py_GIL_DISABLED
1070910714
/* Avoid further slowdowns */
1071010715
if (tp->tp_descr_get == slot_tp_descr_get)
1071110716
tp->tp_descr_get = NULL;
10717+
#endif
1071210718
return Py_NewRef(self);
1071310719
}
1071410720
if (obj == NULL)

Tools/tsan/suppressions_free_threading.txt

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

4545
# gh-133467. Some of these could be hard to trigger.
4646
race_top:_Py_slot_tp_getattr_hook
47-
race_top:slot_tp_descr_get
48-
race_top:type_set_name
4947
race_top:set_tp_bases
5048
race_top:type_set_bases_unlocked

0 commit comments

Comments
 (0)