Skip to content

Commit c15f066

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

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
@@ -1947,22 +1947,34 @@ whichmodule(PickleState *st, PyObject *global, PyObject *global_name, PyObject *
19471947
return NULL;
19481948
}
19491949
if (PyDict_CheckExact(modules)) {
1950+
PyObject *found_name = NULL;
1951+
int error = 0;
19501952
i = 0;
1953+
Py_BEGIN_CRITICAL_SECTION(modules);
19511954
while (PyDict_Next(modules, &i, &module_name, &module)) {
19521955
Py_INCREF(module_name);
19531956
Py_INCREF(module);
19541957
if (_checkmodule(module_name, module, global, dotted_path) == 0) {
19551958
Py_DECREF(module);
1956-
Py_DECREF(modules);
1957-
return module_name;
1959+
found_name = module_name;
1960+
break;
19581961
}
19591962
Py_DECREF(module);
19601963
Py_DECREF(module_name);
19611964
if (PyErr_Occurred()) {
1962-
Py_DECREF(modules);
1963-
return NULL;
1965+
error = 1;
1966+
break;
19641967
}
19651968
}
1969+
Py_END_CRITICAL_SECTION();
1970+
if (error) {
1971+
Py_DECREF(modules);
1972+
return NULL;
1973+
}
1974+
if (found_name != NULL) {
1975+
Py_DECREF(modules);
1976+
return found_name;
1977+
}
19661978
}
19671979
else {
19681980
PyObject *iterator = PyObject_GetIter(modules);

0 commit comments

Comments
 (0)