Skip to content

Commit 40322e6

Browse files
committed
Issue #10241: Clear extension module dict copies at interpreter shutdown.
Patch by Neil Schemenauer, minimally modified. (re-apply after fix for tkinter-related crash)
1 parent 584e815 commit 40322e6

File tree

4 files changed

+33
-0
lines changed

4 files changed

+33
-0
lines changed

Include/pystate.h

+3
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ PyAPI_FUNC(int) PyState_AddModule(PyObject*, struct PyModuleDef*);
134134
PyAPI_FUNC(int) PyState_RemoveModule(struct PyModuleDef*);
135135
#endif
136136
PyAPI_FUNC(PyObject*) PyState_FindModule(struct PyModuleDef*);
137+
#ifndef Py_LIMITED_API
138+
PyAPI_FUNC(void) _PyState_ClearModules(void);
139+
#endif
137140

138141
PyAPI_FUNC(PyThreadState *) PyThreadState_New(PyInterpreterState *);
139142
PyAPI_FUNC(PyThreadState *) _PyThreadState_Prealloc(PyInterpreterState *);

Misc/NEWS

+3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ Core and Builtins
5454

5555
- Issue #17899: Fix rare file descriptor leak in os.listdir().
5656

57+
- Issue #10241: Clear extension module dict copies at interpreter shutdown.
58+
Patch by Neil Schemenauer, minimally modified.
59+
5760
- Issue #9035: ismount now recognises volumes mounted below a drive root
5861
on Windows. Original patch by Atsuo Ishimoto.
5962

Python/import.c

+2
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,8 @@ PyImport_Cleanup(void)
380380
builtins = interp->builtins;
381381
interp->builtins = PyDict_New();
382382
Py_DECREF(builtins);
383+
/* Clear module dict copies stored in the interpreter state */
384+
_PyState_ClearModules();
383385
/* Collect references */
384386
_PyGC_CollectNoFail();
385387
/* Dump GC stats before it's too late, since it uses the warnings

Python/pystate.c

+25
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,31 @@ PyState_RemoveModule(struct PyModuleDef* def)
320320
return PyList_SetItem(state->modules_by_index, index, Py_None);
321321
}
322322

323+
/* used by import.c:PyImport_Cleanup */
324+
void
325+
_PyState_ClearModules(void)
326+
{
327+
PyInterpreterState *state = PyThreadState_GET()->interp;
328+
if (state->modules_by_index) {
329+
Py_ssize_t i;
330+
for (i = 0; i < PyList_GET_SIZE(state->modules_by_index); i++) {
331+
PyObject *m = PyList_GET_ITEM(state->modules_by_index, i);
332+
if (PyModule_Check(m)) {
333+
/* cleanup the saved copy of module dicts */
334+
PyModuleDef *md = PyModule_GetDef(m);
335+
if (md)
336+
Py_CLEAR(md->m_base.m_copy);
337+
}
338+
}
339+
/* Setting modules_by_index to NULL could be dangerous, so we
340+
clear the list instead. */
341+
if (PyList_SetSlice(state->modules_by_index,
342+
0, PyList_GET_SIZE(state->modules_by_index),
343+
NULL))
344+
PyErr_WriteUnraisable(state->modules_by_index);
345+
}
346+
}
347+
323348
void
324349
PyThreadState_Clear(PyThreadState *tstate)
325350
{

0 commit comments

Comments
 (0)