https://github.com/python/cpython/commit/3a248564470075cb8c7b8a75fe7ba61f7ea341b2
commit: 3a248564470075cb8c7b8a75fe7ba61f7ea341b2
branch: main
author: Pieter Eendebak <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2026-03-16T08:53:37Z
summary:

gh-123471: make concurrent iteration over itertools.accumulate thread-safe 
(#144486)

files:
A Misc/NEWS.d/next/Library/2026-02-04-20-30-59.gh-issue-123471.1dnPvs.rst
M Lib/test/test_free_threading/test_itertools.py
M Modules/itertoolsmodule.c

diff --git a/Lib/test/test_free_threading/test_itertools.py 
b/Lib/test/test_free_threading/test_itertools.py
index bb6047e8669475..20135dd3165acf 100644
--- a/Lib/test/test_free_threading/test_itertools.py
+++ b/Lib/test/test_free_threading/test_itertools.py
@@ -1,5 +1,5 @@
 import unittest
-from itertools import batched, chain, combinations_with_replacement, cycle, 
permutations
+from itertools import accumulate, batched, chain, 
combinations_with_replacement, cycle, permutations
 from test.support import threading_helper
 
 
@@ -16,6 +16,13 @@ def work_iterator(it):
 
 class ItertoolsThreading(unittest.TestCase):
 
+    @threading_helper.reap_threads
+    def test_accumulate(self):
+        number_of_iterations = 10
+        for _ in range(number_of_iterations):
+            it = accumulate(tuple(range(40)))
+            threading_helper.run_concurrently(work_iterator, nthreads=10, 
args=[it])
+
     @threading_helper.reap_threads
     def test_batched(self):
         number_of_iterations = 10
diff --git 
a/Misc/NEWS.d/next/Library/2026-02-04-20-30-59.gh-issue-123471.1dnPvs.rst 
b/Misc/NEWS.d/next/Library/2026-02-04-20-30-59.gh-issue-123471.1dnPvs.rst
new file mode 100644
index 00000000000000..d650103e28ee68
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-02-04-20-30-59.gh-issue-123471.1dnPvs.rst
@@ -0,0 +1 @@
+Make concurrent iteration over :class:`itertools.accumulate` safe under 
free-threading.
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index bc25bf6bfc1bd2..b37256c7928bad 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -3073,7 +3073,7 @@ accumulate_traverse(PyObject *op, visitproc visit, void 
*arg)
 }
 
 static PyObject *
-accumulate_next(PyObject *op)
+accumulate_next_lock_held(PyObject *op)
 {
     accumulateobject *lz = accumulateobject_CAST(op);
     PyObject *val, *newtotal;
@@ -3105,6 +3105,16 @@ accumulate_next(PyObject *op)
     return newtotal;
 }
 
+static PyObject *
+accumulate_next(PyObject *op)
+{
+    PyObject *result;
+    Py_BEGIN_CRITICAL_SECTION(op);
+    result = accumulate_next_lock_held(op);
+    Py_END_CRITICAL_SECTION()
+    return result;
+}
+
 static PyType_Slot accumulate_slots[] = {
     {Py_tp_dealloc, accumulate_dealloc},
     {Py_tp_getattro, PyObject_GenericGetAttr},

_______________________________________________
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]

Reply via email to