Skip to content

Commit b65c282

Browse files
[3.15] gh-150157: Fix critical section for PyDict_Next() in _pickle.c (GH-150158) (#150711)
(cherry picked from commit c5516e7) Co-authored-by: Thomas Kowalski <thom.kowa@gmail.com>
1 parent e60e8cf commit b65c282

2 files changed

Lines changed: 19 additions & 4 deletions

File tree

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix a crash in free-threaded builds that occurs when pickling by name
2+
objects without a ``__module__`` attribute while :data:`sys.modules`
3+
is concurrently being modified.

Modules/_pickle.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2055,22 +2055,34 @@ whichmodule(PickleState *st, PyObject *global, PyObject *global_name, PyObject *
20552055
return NULL;
20562056
}
20572057
if (PyDict_CheckExact(modules)) {
2058+
PyObject *found_name = NULL;
2059+
int error = 0;
20582060
i = 0;
2061+
Py_BEGIN_CRITICAL_SECTION(modules);
20592062
while (PyDict_Next(modules, &i, &module_name, &module)) {
20602063
Py_INCREF(module_name);
20612064
Py_INCREF(module);
20622065
if (_checkmodule(module_name, module, global, dotted_path) == 0) {
20632066
Py_DECREF(module);
2064-
Py_DECREF(modules);
2065-
return module_name;
2067+
found_name = module_name;
2068+
break;
20662069
}
20672070
Py_DECREF(module);
20682071
Py_DECREF(module_name);
20692072
if (PyErr_Occurred()) {
2070-
Py_DECREF(modules);
2071-
return NULL;
2073+
error = 1;
2074+
break;
20722075
}
20732076
}
2077+
Py_END_CRITICAL_SECTION();
2078+
if (error) {
2079+
Py_DECREF(modules);
2080+
return NULL;
2081+
}
2082+
if (found_name != NULL) {
2083+
Py_DECREF(modules);
2084+
return found_name;
2085+
}
20742086
}
20752087
else {
20762088
PyObject *iterator = PyObject_GetIter(modules);

0 commit comments

Comments
 (0)