From e77b639554500903aa9ec6927e3921cddb5d7a47 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Tue, 3 Feb 2026 14:16:53 +0100 Subject: [PATCH 1/6] Make accumulate thread-safe --- Modules/itertoolsmodule.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 7e73f76bc20b58..dbb19c731543d9 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -3063,7 +3063,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; @@ -3095,6 +3095,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}, From 2621b8847e13e1e2fc428d7b609304053f444a5a Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Wed, 4 Feb 2026 21:22:14 +0100 Subject: [PATCH 2/6] add ft test for accumulate --- Lib/test/test_free_threading/test_itertools.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_free_threading/test_itertools.py b/Lib/test/test_free_threading/test_itertools.py index bb6047e8669475..503fb71a5f69b7 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(500))) + threading_helper.run_concurrently(work_iterator, nthreads=10, args=[it]) + @threading_helper.reap_threads def test_batched(self): number_of_iterations = 10 From bd4fa041e85aa403eb9c2b3f4fec9fc1c3e56860 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Wed, 4 Feb 2026 21:29:32 +0100 Subject: [PATCH 3/6] reduce test duration --- Lib/test/test_free_threading/test_itertools.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_free_threading/test_itertools.py b/Lib/test/test_free_threading/test_itertools.py index 503fb71a5f69b7..20135dd3165acf 100644 --- a/Lib/test/test_free_threading/test_itertools.py +++ b/Lib/test/test_free_threading/test_itertools.py @@ -20,7 +20,7 @@ class ItertoolsThreading(unittest.TestCase): def test_accumulate(self): number_of_iterations = 10 for _ in range(number_of_iterations): - it = accumulate(tuple(range(500))) + it = accumulate(tuple(range(40))) threading_helper.run_concurrently(work_iterator, nthreads=10, args=[it]) @threading_helper.reap_threads From 124450b8963d65e36e9257f146240e88914aaa59 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Wed, 4 Feb 2026 20:31:04 +0000 Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2026-02-04-20-30-59.gh-issue-123471.1dnPvs.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2026-02-04-20-30-59.gh-issue-123471.1dnPvs.rst 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. From 2511892b4d991ffa40ec7bc08ee32e2e634ff8b8 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Thu, 5 Feb 2026 20:40:30 +0000 Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Library/2026-02-05-20-40-20.gh-issue-123471.Uj-Eyr.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2026-02-05-20-40-20.gh-issue-123471.Uj-Eyr.rst diff --git a/Misc/NEWS.d/next/Library/2026-02-05-20-40-20.gh-issue-123471.Uj-Eyr.rst b/Misc/NEWS.d/next/Library/2026-02-05-20-40-20.gh-issue-123471.Uj-Eyr.rst new file mode 100644 index 00000000000000..52bc301b439943 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-02-05-20-40-20.gh-issue-123471.Uj-Eyr.rst @@ -0,0 +1 @@ +Make concurrent iterations over :class:`itertools.islice` safe under free-threading. From 06fef05283378d4e39daad877070d19570ebea92 Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Thu, 5 Feb 2026 21:42:25 +0100 Subject: [PATCH 6/6] Delete Misc/NEWS.d/next/Library/2026-02-05-20-40-20.gh-issue-123471.Uj-Eyr.rst --- .../next/Library/2026-02-05-20-40-20.gh-issue-123471.Uj-Eyr.rst | 1 - 1 file changed, 1 deletion(-) delete mode 100644 Misc/NEWS.d/next/Library/2026-02-05-20-40-20.gh-issue-123471.Uj-Eyr.rst diff --git a/Misc/NEWS.d/next/Library/2026-02-05-20-40-20.gh-issue-123471.Uj-Eyr.rst b/Misc/NEWS.d/next/Library/2026-02-05-20-40-20.gh-issue-123471.Uj-Eyr.rst deleted file mode 100644 index 52bc301b439943..00000000000000 --- a/Misc/NEWS.d/next/Library/2026-02-05-20-40-20.gh-issue-123471.Uj-Eyr.rst +++ /dev/null @@ -1 +0,0 @@ -Make concurrent iterations over :class:`itertools.islice` safe under free-threading.