]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-133980: use atomic store in `PyObject_GenericSetDict` (#133988)
authorKumar Aditya <kumaraditya@python.org>
Tue, 20 May 2025 15:41:47 +0000 (21:11 +0530)
committerGitHub <noreply@github.com>
Tue, 20 May 2025 15:41:47 +0000 (21:11 +0530)
Lib/test/test_free_threading/test_dict.py
Objects/object.c

index 476cc3178d843f6cee40a27aa279bce5cfa1b991..5d5d4e226caa4085458b971d4af348ac8f074b4d 100644 (file)
@@ -228,6 +228,22 @@ class TestDict(TestCase):
 
             self.assertEqual(count, 0)
 
+    def test_racing_object_get_set_dict(self):
+        e = Exception()
+
+        def writer():
+            for i in range(10000):
+                e.__dict__ = {1:2}
+
+        def reader():
+            for i in range(10000):
+                e.__dict__
+
+        t1 = Thread(target=writer)
+        t2 = Thread(target=reader)
+
+        with threading_helper.start_threads([t1, t2]):
+            pass
 
 if __name__ == "__main__":
     unittest.main()
index 723b0427e69251520db590c67b44e98113d0b476..af1aa217f7546217bd29ccd0fab8251b33813e75 100644 (file)
@@ -1931,7 +1931,13 @@ PyObject_GenericSetDict(PyObject *obj, PyObject *value, void *context)
         return -1;
     }
     Py_BEGIN_CRITICAL_SECTION(obj);
-    Py_XSETREF(*dictptr, Py_NewRef(value));
+    PyObject *olddict = *dictptr;
+    FT_ATOMIC_STORE_PTR_RELEASE(*dictptr, Py_NewRef(value));
+#ifdef Py_GIL_DISABLED
+    _PyObject_XDecRefDelayed(olddict);
+#else
+    Py_XDECREF(olddict);
+#endif
     Py_END_CRITICAL_SECTION();
     return 0;
 }