From 0a581a1e0b788bff5ef8ba8e4d2085183353d28d Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Fri, 10 Apr 2026 18:49:54 +0200 Subject: [PATCH 1/2] Make itertools.islice safe in the FT build --- Lib/test/test_free_threading/test_itertools.py | 9 ++++++++- Modules/itertoolsmodule.c | 12 +++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_free_threading/test_itertools.py b/Lib/test/test_free_threading/test_itertools.py index 670d4ca8835e0d..f8553906e19f42 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 accumulate, batched, chain, combinations_with_replacement, cycle, permutations, zip_longest +from itertools import accumulate, batched, chain, combinations_with_replacement, cycle, islice, permutations, zip_longest from test.support import threading_helper @@ -55,6 +55,13 @@ def test_combinations_with_replacement(self): it = combinations_with_replacement(tuple(range(2)), 2) threading_helper.run_concurrently(work_iterator, nthreads=6, args=[it]) + @threading_helper.reap_threads + def test_islice(self): + number_of_iterations = 6 + for _ in range(number_of_iterations): + it = islice(tuple(range(10)), 1, 8, 2) + threading_helper.run_concurrently(work_iterator, nthreads=10, args=[it]) + @threading_helper.reap_threads def test_permutations(self): number_of_iterations = 6 diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index a6bfa78a461bb0..3e54d795458a47 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -1624,7 +1624,7 @@ islice_traverse(PyObject *op, visitproc visit, void *arg) } static PyObject * -islice_next(PyObject *op) +islice_next_lock_held(PyObject *op) { isliceobject *lz = isliceobject_CAST(op); PyObject *item; @@ -1663,6 +1663,16 @@ islice_next(PyObject *op) return NULL; } +static PyObject * +islice_next(PyObject *op) +{ + PyObject *result; + Py_BEGIN_CRITICAL_SECTION(op); + result = islice_next_lock_held(op); + Py_END_CRITICAL_SECTION(); + return result; +} + PyDoc_STRVAR(islice_doc, "islice(iterable, stop) --> islice object\n\ islice(iterable, start, stop[, step]) --> islice object\n\ From 5ee09e19bd7bdcfd3b37719f9467f441f09e06ac Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Fri, 10 Apr 2026 18:57:39 +0200 Subject: [PATCH 2/2] news entry --- .../Library/2026-04-10-00-00-00.gh-issue-123471.islice_ft.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2026-04-10-00-00-00.gh-issue-123471.islice_ft.rst diff --git a/Misc/NEWS.d/next/Library/2026-04-10-00-00-00.gh-issue-123471.islice_ft.rst b/Misc/NEWS.d/next/Library/2026-04-10-00-00-00.gh-issue-123471.islice_ft.rst new file mode 100644 index 00000000000000..5061c89259a4f3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-04-10-00-00-00.gh-issue-123471.islice_ft.rst @@ -0,0 +1,2 @@ +Make concurrent iteration over :class:`itertools.islice` safe under +free-threading.