https://github.com/python/cpython/commit/f586fd9e304e6747fdebe2477355beb059724571
commit: f586fd9e304e6747fdebe2477355beb059724571
branch: main
author: Brij Kapadia <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2026-05-30T21:07:27+05:30
summary:
gh-144774: Add critical section in `BaseException.__setstate__` (#150578)
files:
A Lib/test/test_free_threading/test_exceptions.py
A
Misc/NEWS.d/next/Core_and_Builtins/2026-05-29-17-51-11.gh-issue-144774.jPcixe.rst
M Objects/clinic/exceptions.c.h
M 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
index 000000000000000..61146f29c7868e5
--- /dev/null
+++ b/Lib/test/test_free_threading/test_exceptions.py
@@ -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
index 000000000000000..3dd117e7d3c3502
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-29-17-51-11.gh-issue-144774.jPcixe.rst
@@ -0,0 +1 @@
+Fix data race in :class:`BaseException` when an exception is copied while
being mutated.
diff --git a/Objects/clinic/exceptions.c.h b/Objects/clinic/exceptions.c.h
index 9baac8b1cc660b0..5047a673e579c66 100644
--- a/Objects/clinic/exceptions.c.h
+++ b/Objects/clinic/exceptions.c.h
@@ -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]*/
diff --git a/Objects/exceptions.c b/Objects/exceptions.c
index 5e5e87cd6d7559f..ce1e6d93da3fc45 100644
--- a/Objects/exceptions.c
+++ b/Objects/exceptions.c
@@ -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;
_______________________________________________
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]