https://github.com/python/cpython/commit/b3a38438d83245e52dff80f348c7fde539333cea
commit: b3a38438d83245e52dff80f348c7fde539333cea
branch: main
author: Alper <[email protected]>
committer: corona10 <[email protected]>
date: 2025-10-22T09:14:48+09:00
summary:

gh-116738: Make _suggestions module thread-safe (gh-140321)

files:
A Lib/test/test_free_threading/test_suggestions.py
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-10-18-19-52-20.gh-issue-116738.NLJW0L.rst
M Modules/_suggestions.c
M Modules/clinic/_suggestions.c.h

diff --git a/Lib/test/test_free_threading/test_suggestions.py 
b/Lib/test/test_free_threading/test_suggestions.py
new file mode 100755
index 00000000000000..2c10a511b86595
--- /dev/null
+++ b/Lib/test/test_free_threading/test_suggestions.py
@@ -0,0 +1,24 @@
+import unittest
+
+from test.support import import_helper, threading_helper
+from test.support.threading_helper import run_concurrently
+
+suggestions = import_helper.import_module("_suggestions")
+
+NTHREADS = 10
+
+
+@threading_helper.requires_working_threading()
+class SuggestionsTests(unittest.TestCase):
+    def test_generate_suggestions(self):
+        candidates = [str(i) for i in range(100)]
+
+        def worker():
+            _ = suggestions._generate_suggestions(candidates, "42")
+            candidates.clear()
+
+        run_concurrently(worker_func=worker, nthreads=NTHREADS)
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-10-18-19-52-20.gh-issue-116738.NLJW0L.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-18-19-52-20.gh-issue-116738.NLJW0L.rst
new file mode 100644
index 00000000000000..bf323b870bc631
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-10-18-19-52-20.gh-issue-116738.NLJW0L.rst
@@ -0,0 +1,2 @@
+Make _suggestions module thread-safe on the :term:`free threaded <free
+threading>` build.
diff --git a/Modules/_suggestions.c b/Modules/_suggestions.c
index b8bc6db2477281..fb588de78085fe 100644
--- a/Modules/_suggestions.c
+++ b/Modules/_suggestions.c
@@ -8,6 +8,7 @@ module _suggestions
 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=e58d81fafad5637b]*/
 
 /*[clinic input]
+@critical_section candidates
 _suggestions._generate_suggestions
     candidates: object
     item: unicode
@@ -18,7 +19,7 @@ Returns the candidate in candidates that's closest to item
 static PyObject *
 _suggestions__generate_suggestions_impl(PyObject *module,
                                         PyObject *candidates, PyObject *item)
-/*[clinic end generated code: output=79be7b653ae5e7ca input=ba2a8dddc654e33a]*/
+/*[clinic end generated code: output=79be7b653ae5e7ca input=92861a6c9bd8f667]*/
 {
    // Check if dir is a list
     if (!PyList_CheckExact(candidates)) {
@@ -29,7 +30,7 @@ _suggestions__generate_suggestions_impl(PyObject *module,
     // Check if all elements in the list are Unicode
     Py_ssize_t size = PyList_Size(candidates);
     for (Py_ssize_t i = 0; i < size; ++i) {
-        PyObject *elem = PyList_GetItem(candidates, i);
+        PyObject *elem = PyList_GET_ITEM(candidates, i);
         if (!PyUnicode_Check(elem)) {
             PyErr_SetString(PyExc_TypeError, "all elements in 'candidates' 
must be strings");
             return NULL;
diff --git a/Modules/clinic/_suggestions.c.h b/Modules/clinic/_suggestions.c.h
index 51484b13d5af89..3b3ed5056ac8d0 100644
--- a/Modules/clinic/_suggestions.c.h
+++ b/Modules/clinic/_suggestions.c.h
@@ -2,6 +2,7 @@
 preserve
 [clinic start generated code]*/
 
+#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
 #include "pycore_modsupport.h"    // _PyArg_CheckPositional()
 
 PyDoc_STRVAR(_suggestions__generate_suggestions__doc__,
@@ -33,9 +34,11 @@ _suggestions__generate_suggestions(PyObject *module, 
PyObject *const *args, Py_s
         goto exit;
     }
     item = args[1];
+    Py_BEGIN_CRITICAL_SECTION(candidates);
     return_value = _suggestions__generate_suggestions_impl(module, candidates, 
item);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=1d8e963cdae30b13 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=1690dd15a464d19c input=a9049054013a1b77]*/

_______________________________________________
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