https://github.com/python/cpython/commit/1604043caf0a00fe4ea9f6e31e389c4cf8b8baab
commit: 1604043caf0a00fe4ea9f6e31e389c4cf8b8baab
branch: main
author: L. Le <[email protected]>
committer: encukou <[email protected]>
date: 2026-07-19T15:20:56+02:00
summary:
gh-153932: protect read of en_index during enumerate.reduce (GH-154118)
files:
A
Misc/NEWS.d/next/Core_and_Builtins/2026-07-19-12-33-27.gh-issue-153932.lKw2bo.rst
M Lib/test/libregrtest/tsan.py
M Lib/test/test_enumerate.py
M Objects/enumobject.c
diff --git a/Lib/test/libregrtest/tsan.py b/Lib/test/libregrtest/tsan.py
index bacfe5e21ba0b7d..c7ec63763bc9d85 100644
--- a/Lib/test/libregrtest/tsan.py
+++ b/Lib/test/libregrtest/tsan.py
@@ -8,6 +8,7 @@
'test_ctypes',
'test_concurrent_futures',
'test_enum',
+ 'test_enumerate',
'test_functools',
'test_httpservers',
'test_imaplib',
diff --git a/Lib/test/test_enumerate.py b/Lib/test/test_enumerate.py
index 5cb54cff9b76fdd..c8b85fe86921781 100644
--- a/Lib/test/test_enumerate.py
+++ b/Lib/test/test_enumerate.py
@@ -3,8 +3,11 @@
import sys
import pickle
import gc
+import threading
+
from test import support
+from test.support import threading_helper
class G:
'Sequence using __getitem__'
@@ -292,5 +295,28 @@ def enum(self, iterable, start=sys.maxsize + 1):
(sys.maxsize+3,'c')]
+@threading_helper.requires_working_threading()
+class TestThreadSafety(EnumerateStartTestCase):
+ def test_thread_safety_while_iterating(self):
+ # gh-153932: calling reduce while iterating should pass with TSAN
+
+ en = enumerate(range(10_000))
+ stop = threading.Event()
+
+ def advance():
+ for _ in en:
+ pass
+ stop.set()
+
+ def read():
+ while not stop.is_set():
+ en.__reduce__()
+
+ threads = [threading.Thread(target=advance),
threading.Thread(target=read)]
+
+ with threading_helper.start_threads(threads):
+ pass
+
+
if __name__ == "__main__":
unittest.main()
diff --git
a/Misc/NEWS.d/next/Core_and_Builtins/2026-07-19-12-33-27.gh-issue-153932.lKw2bo.rst
b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-19-12-33-27.gh-issue-153932.lKw2bo.rst
new file mode 100644
index 000000000000000..56b96307ed04cd9
--- /dev/null
+++
b/Misc/NEWS.d/next/Core_and_Builtins/2026-07-19-12-33-27.gh-issue-153932.lKw2bo.rst
@@ -0,0 +1,2 @@
+Fix thread safety issue in the ``__reduce__`` method of
+:py:class:`enumerate`.
diff --git a/Objects/enumobject.c b/Objects/enumobject.c
index fc53f1bfee8dde4..68aa594c5540cee 100644
--- a/Objects/enumobject.c
+++ b/Objects/enumobject.c
@@ -277,10 +277,13 @@ enum_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
enumobject *en = _enumobject_CAST(op);
PyObject *result;
Py_BEGIN_CRITICAL_SECTION(en);
- if (en->en_longindex != NULL)
+ if (en->en_longindex != NULL) {
result = Py_BuildValue("O(OO)", Py_TYPE(en), en->en_sit,
en->en_longindex);
- else
- result = Py_BuildValue("O(On)", Py_TYPE(en), en->en_sit, en->en_index);
+ }
+ else {
+ Py_ssize_t en_index = FT_ATOMIC_LOAD_SSIZE_RELAXED(en->en_index);
+ result = Py_BuildValue("O(On)", Py_TYPE(en), en->en_sit, en_index);
+ }
Py_END_CRITICAL_SECTION();
return result;
}
_______________________________________________
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]