https://github.com/python/cpython/commit/9214e3f33eeeb0ee862777378f98fdeb7b6944c6
commit: 9214e3f33eeeb0ee862777378f98fdeb7b6944c6
branch: main
author: Pieter Eendebak <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2026-03-27T19:31:49+05:30
summary:

gh-123471: Make `itertools.zip_longest` safe in the FT build (#146033)

files:
A Misc/NEWS.d/next/Library/2026-03-17-19-51-05.gh-issue-123471.oY4UR5.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 20135dd3165acf..670d4ca8835e0d 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
+from itertools import accumulate, batched, chain, 
combinations_with_replacement, cycle, permutations, zip_longest
 from test.support import threading_helper
 
 
@@ -62,6 +62,13 @@ def test_permutations(self):
             it = permutations(tuple(range(4)), 2)
             threading_helper.run_concurrently(work_iterator, nthreads=6, 
args=[it])
 
+    @threading_helper.reap_threads
+    def test_zip_longest(self):
+        number_of_iterations = 10
+        for _ in range(number_of_iterations):
+            it = zip_longest(list(range(4)), list(range(8)), fillvalue=0)
+            threading_helper.run_concurrently(work_iterator, nthreads=10, 
args=[it])
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git 
a/Misc/NEWS.d/next/Library/2026-03-17-19-51-05.gh-issue-123471.oY4UR5.rst 
b/Misc/NEWS.d/next/Library/2026-03-17-19-51-05.gh-issue-123471.oY4UR5.rst
new file mode 100644
index 00000000000000..8d2e1b970e8171
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-03-17-19-51-05.gh-issue-123471.oY4UR5.rst
@@ -0,0 +1 @@
+Make concurrent iteration over :class:`itertools.zip_longest` safe under 
free-threading.
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index 48f1d1c7fde17b..cf49724b8861c2 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -3876,7 +3876,7 @@ zip_longest_traverse(PyObject *op, visitproc visit, void 
*arg)
 }
 
 static PyObject *
-zip_longest_next(PyObject *op)
+zip_longest_next_lock_held(PyObject *op)
 {
     ziplongestobject *lz = ziplongestobject_CAST(op);
     Py_ssize_t i;
@@ -3947,6 +3947,16 @@ zip_longest_next(PyObject *op)
     return result;
 }
 
+static PyObject *
+zip_longest_next(PyObject *op)
+{
+    PyObject *result;
+    Py_BEGIN_CRITICAL_SECTION(op);
+    result = zip_longest_next_lock_held(op);
+    Py_END_CRITICAL_SECTION()
+    return result;
+}
+
 PyDoc_STRVAR(zip_longest_doc,
 "zip_longest(*iterables, fillvalue=None)\n\
 --\n\

_______________________________________________
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