https://github.com/python/cpython/commit/e99bc7fd44bbbf2464c37d5a57777ac0e1264c37
commit: e99bc7fd44bbbf2464c37d5a57777ac0e1264c37
branch: main
author: Kumar Aditya <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2025-08-01T13:40:40Z
summary:
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.
files:
M Lib/test/test_free_threading/test_type.py
M Objects/typeobject.c
M Tools/tsan/suppressions_free_threading.txt
diff --git a/Lib/test/test_free_threading/test_type.py
b/Lib/test/test_free_threading/test_type.py
index ae996e7db3c7fd..2d995751005d71 100644
--- a/Lib/test/test_free_threading/test_type.py
+++ b/Lib/test/test_free_threading/test_type.py
@@ -127,6 +127,20 @@ class ClassB(Base):
obj.__class__ = ClassB
+ def test_name_change(self):
+ class Foo:
+ pass
+
+ def writer():
+ for _ in range(1000):
+ Foo.__name__ = 'Bar'
+
+ def reader():
+ for _ in range(1000):
+ Foo.__name__
+
+ self.run_one(writer, reader)
+
def run_one(self, writer_func, reader_func):
barrier = threading.Barrier(NTHREADS)
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index d952a58d94af55..6e67b6e01cb8b8 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -1535,9 +1535,13 @@ type_set_name(PyObject *tp, PyObject *value, void
*Py_UNUSED(closure))
return -1;
}
+ PyInterpreterState *interp = _PyInterpreterState_GET();
+ _PyEval_StopTheWorld(interp);
type->tp_name = tp_name;
- Py_SETREF(((PyHeapTypeObject*)type)->ht_name, Py_NewRef(value));
-
+ PyObject *old_name = ((PyHeapTypeObject*)type)->ht_name;
+ ((PyHeapTypeObject*)type)->ht_name = Py_NewRef(value);
+ _PyEval_StartTheWorld(interp);
+ Py_DECREF(old_name);
return 0;
}
@@ -10706,9 +10710,11 @@ slot_tp_descr_get(PyObject *self, PyObject *obj,
PyObject *type)
get = _PyType_LookupRef(tp, &_Py_ID(__get__));
if (get == NULL) {
+#ifndef Py_GIL_DISABLED
/* Avoid further slowdowns */
if (tp->tp_descr_get == slot_tp_descr_get)
tp->tp_descr_get = NULL;
+#endif
return Py_NewRef(self);
}
if (obj == NULL)
diff --git a/Tools/tsan/suppressions_free_threading.txt
b/Tools/tsan/suppressions_free_threading.txt
index 93421b623b92f9..52d7c25a5bb37a 100644
--- a/Tools/tsan/suppressions_free_threading.txt
+++ b/Tools/tsan/suppressions_free_threading.txt
@@ -44,7 +44,5 @@ race:PyObject_Realloc
# gh-133467. Some of these could be hard to trigger.
race_top:_Py_slot_tp_getattr_hook
-race_top:slot_tp_descr_get
-race_top:type_set_name
race_top:set_tp_bases
race_top:type_set_bases_unlocked
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]