]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-133467: fix data race in `type_set_name` (#137302)
authorKumar Aditya <kumaraditya@python.org>
Fri, 1 Aug 2025 13:40:40 +0000 (19:10 +0530)
committerGitHub <noreply@github.com>
Fri, 1 Aug 2025 13:40:40 +0000 (13:40 +0000)
Fix data race in `type_set_name` by assigning name under stop the world pause making it thread safe in free-threading.

Lib/test/test_free_threading/test_type.py
Objects/typeobject.c
Tools/tsan/suppressions_free_threading.txt

index ae996e7db3c7fd7fddded99311270e6393992157..2d995751005d710fac5b5c5f86a8bd1e1a8238f3 100644 (file)
@@ -127,6 +127,20 @@ class TestType(TestCase):
         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)
 
index d952a58d94af55b4095a29f79446233271c7ab0c..6e67b6e01cb8b8fda285885292d08b9321a384b0 100644 (file)
@@ -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)
index 93421b623b92f9fec01eaea6e7ca47b742f42e1c..52d7c25a5bb37afe7a41915c98875044cc74b356 100644 (file)
@@ -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