https://github.com/python/cpython/commit/c5516e7e371f7b273eb37c7b65f14ef14ee81f11
commit: c5516e7e371f7b273eb37c7b65f14ef14ee81f11
branch: main
author: Thomas Kowalski <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-06-01T17:32:13+03:00
summary:

gh-150157: Fix critical section for PyDict_Next() in _pickle.c (GH-150158)

files:
A Misc/NEWS.d/next/Library/2026-05-21-20-47-45.gh-issue-150157.ZvmO-bQZ.rst
M Modules/_pickle.c

diff --git 
a/Misc/NEWS.d/next/Library/2026-05-21-20-47-45.gh-issue-150157.ZvmO-bQZ.rst 
b/Misc/NEWS.d/next/Library/2026-05-21-20-47-45.gh-issue-150157.ZvmO-bQZ.rst
new file mode 100644
index 00000000000000..3a12e26cf736f7
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-05-21-20-47-45.gh-issue-150157.ZvmO-bQZ.rst
@@ -0,0 +1,3 @@
+Fix a crash in free-threaded builds that occurs when pickling by name
+objects without a ``__module__`` attribute while :data:`sys.modules`
+is concurrently being modified.
diff --git a/Modules/_pickle.c b/Modules/_pickle.c
index 2d82438f0d308d..a5595be251a738 100644
--- a/Modules/_pickle.c
+++ b/Modules/_pickle.c
@@ -2055,22 +2055,34 @@ whichmodule(PickleState *st, PyObject *global, PyObject 
*global_name, PyObject *
             return NULL;
         }
         if (PyDict_CheckExact(modules)) {
+            PyObject *found_name = NULL;
+            int error = 0;
             i = 0;
+            Py_BEGIN_CRITICAL_SECTION(modules);
             while (PyDict_Next(modules, &i, &module_name, &module)) {
                 Py_INCREF(module_name);
                 Py_INCREF(module);
                 if (_checkmodule(module_name, module, global, dotted_path) == 
0) {
                     Py_DECREF(module);
-                    Py_DECREF(modules);
-                    return module_name;
+                    found_name = module_name;
+                    break;
                 }
                 Py_DECREF(module);
                 Py_DECREF(module_name);
                 if (PyErr_Occurred()) {
-                    Py_DECREF(modules);
-                    return NULL;
+                    error = 1;
+                    break;
                 }
             }
+            Py_END_CRITICAL_SECTION();
+            if (error) {
+                Py_DECREF(modules);
+                return NULL;
+            }
+            if (found_name != NULL) {
+                Py_DECREF(modules);
+                return found_name;
+            }
         }
         else {
             PyObject *iterator = PyObject_GetIter(modules);

_______________________________________________
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