diff --git a/Include/pystate.h b/Include/pystate.h index 7b6b602..c0f493b 100644 --- a/Include/pystate.h +++ b/Include/pystate.h @@ -112,6 +112,7 @@ PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_New(void); PyAPI_FUNC(void) PyInterpreterState_Clear(PyInterpreterState *); PyAPI_FUNC(void) PyInterpreterState_Delete(PyInterpreterState *); PyAPI_FUNC(int) _PyState_AddModule(PyObject*, struct PyModuleDef*); +PyAPI_FUNC(void) _PyState_ClearModules(void); PyAPI_FUNC(PyObject*) PyState_FindModule(struct PyModuleDef*); PyAPI_FUNC(PyThreadState *) PyThreadState_New(PyInterpreterState *); diff --git a/Python/import.c b/Python/import.c index 523a1c0..d60566d 100644 --- a/Python/import.c +++ b/Python/import.c @@ -463,6 +463,9 @@ PyImport_Cleanup(void) PyDict_SetItemString(modules, "__main__", Py_None); } + /* cleanup module dict copies stored in the interpreter state */ + _PyState_ClearModules(); + /* The special treatment of "builtins" here is because even when it's not referenced as a module, its dictionary is referenced by almost every module's __builtins__. Since diff --git a/Python/pystate.c b/Python/pystate.c index d5d98b0..975e20f 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -267,6 +267,26 @@ _PyState_AddModule(PyObject* module, struct PyModuleDef* def) def->m_base.m_index, module); } +/* used by import.c:PyImport_Cleanup */ +void +_PyState_ClearModules(void) +{ + PyInterpreterState *state = PyThreadState_GET()->interp; + if (state->modules_by_index) { + Py_ssize_t i; + for (i = 0; i < PyList_GET_SIZE(state->modules_by_index); i++) { + PyObject *m = PyList_GET_ITEM(state->modules_by_index, i); + if (PyModule_Check(m)) { + /* cleanup copy of module dicts */ + PyModuleDef *md = PyModule_GetDef(m); + if (md) + Py_CLEAR(md->m_base.m_copy); + } + } + Py_CLEAR(state->modules_by_index); + } +} + void PyThreadState_Clear(PyThreadState *tstate) {