]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-144774: Add critical section in `BaseException.__setstate__` (#150578)
authorBrij Kapadia <97006829+brijkapadia@users.noreply.github.com>
Sat, 30 May 2026 15:37:27 +0000 (11:37 -0400)
committerGitHub <noreply@github.com>
Sat, 30 May 2026 15:37:27 +0000 (21:07 +0530)
Lib/test/test_free_threading/test_exceptions.py [new file with mode: 0644]
Misc/NEWS.d/next/Core_and_Builtins/2026-05-29-17-51-11.gh-issue-144774.jPcixe.rst [new file with mode: 0644]
Objects/clinic/exceptions.c.h
Objects/exceptions.c

diff --git a/Lib/test/test_free_threading/test_exceptions.py b/Lib/test/test_free_threading/test_exceptions.py
new file mode 100644 (file)
index 0000000..61146f2
--- /dev/null
@@ -0,0 +1,16 @@
+import unittest
+import copy
+
+from test.support import threading_helper
+
+threading_helper.requires_working_threading(module=True)
+class ExceptionTests(unittest.TestCase):
+    def test_setstate_data_race(self):
+        E = Exception()
+
+        def func():
+            for i in range(100):
+                setattr(E, 'x', i)
+                copy.copy(E)
+
+        threading_helper.run_concurrently(func, nthreads=4)
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-05-29-17-51-11.gh-issue-144774.jPcixe.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-29-17-51-11.gh-issue-144774.jPcixe.rst
new file mode 100644 (file)
index 0000000..3dd117e
--- /dev/null
@@ -0,0 +1 @@
+Fix data race in :class:`BaseException` when an exception is copied while being mutated.
index 9baac8b1cc660b028a40071af6994582cfaaf6c9..5047a673e579c6620dcab5849fff1e3b93900279 100644 (file)
@@ -44,7 +44,7 @@ BaseException___setstate__(PyObject *self, PyObject *state)
 {
     PyObject *return_value = NULL;
 
-    Py_BEGIN_CRITICAL_SECTION(self);
+    Py_BEGIN_CRITICAL_SECTION(state);
     return_value = BaseException___setstate___impl((PyBaseExceptionObject *)self, state);
     Py_END_CRITICAL_SECTION();
 
@@ -380,4 +380,4 @@ BaseExceptionGroup_subgroup(PyObject *self, PyObject *matcher_value)
 
     return return_value;
 }
-/*[clinic end generated code: output=fcf70b3b71f3d14a input=a9049054013a1b77]*/
+/*[clinic end generated code: output=e63b88d0443b4f92 input=a9049054013a1b77]*/
index 5e5e87cd6d7559f9dc97016b991d2c598a08b381..ce1e6d93da3fc453d415107a30ac8fcda3932633 100644 (file)
@@ -225,7 +225,7 @@ BaseException___reduce___impl(PyBaseExceptionObject *self)
  */
 
 /*[clinic input]
-@critical_section
+@critical_section state
 BaseException.__setstate__
     state: object
     /
@@ -233,7 +233,7 @@ BaseException.__setstate__
 
 static PyObject *
 BaseException___setstate___impl(PyBaseExceptionObject *self, PyObject *state)
-/*[clinic end generated code: output=f3834889950453ab input=5524b61cfe9b9856]*/
+/*[clinic end generated code: output=f3834889950453ab input=f9b1aea70382cdb6]*/
 {
     PyObject *d_key, *d_value;
     Py_ssize_t i = 0;