From 4ad0caf6e614b82682471da106f11b0a0ee21dc4 Mon Sep 17 00:00:00 2001 From: Kumar Aditya Date: Tue, 20 May 2025 21:11:47 +0530 Subject: [PATCH] gh-133980: use atomic store in `PyObject_GenericSetDict` (GH-133988) (cherry picked from commit ec39fd2c20323ee9814a1137b1a0819e92efae4e) Co-authored-by: Kumar Aditya --- Lib/test/test_free_threading/test_dict.py | 16 ++++++++++++++++ Objects/object.c | 8 +++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_free_threading/test_dict.py b/Lib/test/test_free_threading/test_dict.py index 476cc3178d843f..5d5d4e226caa40 100644 --- a/Lib/test/test_free_threading/test_dict.py +++ b/Lib/test/test_free_threading/test_dict.py @@ -228,6 +228,22 @@ def reader_func(): 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() diff --git a/Objects/object.c b/Objects/object.c index 723b0427e69251..af1aa217f75462 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -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; }