File tree 4 files changed +33
-0
lines changed
4 files changed +33
-0
lines changed Original file line number Diff line number Diff line change @@ -134,6 +134,9 @@ PyAPI_FUNC(int) PyState_AddModule(PyObject*, struct PyModuleDef*);
134
134
PyAPI_FUNC (int ) PyState_RemoveModule (struct PyModuleDef * );
135
135
#endif
136
136
PyAPI_FUNC (PyObject * ) PyState_FindModule (struct PyModuleDef * );
137
+ #ifndef Py_LIMITED_API
138
+ PyAPI_FUNC (void ) _PyState_ClearModules (void );
139
+ #endif
137
140
138
141
PyAPI_FUNC (PyThreadState * ) PyThreadState_New (PyInterpreterState * );
139
142
PyAPI_FUNC (PyThreadState * ) _PyThreadState_Prealloc (PyInterpreterState * );
Original file line number Diff line number Diff line change @@ -54,6 +54,9 @@ Core and Builtins
54
54
55
55
- Issue #17899: Fix rare file descriptor leak in os.listdir().
56
56
57
+ - Issue #10241: Clear extension module dict copies at interpreter shutdown.
58
+ Patch by Neil Schemenauer, minimally modified.
59
+
57
60
- Issue #9035: ismount now recognises volumes mounted below a drive root
58
61
on Windows. Original patch by Atsuo Ishimoto.
59
62
Original file line number Diff line number Diff line change @@ -380,6 +380,8 @@ PyImport_Cleanup(void)
380
380
builtins = interp -> builtins ;
381
381
interp -> builtins = PyDict_New ();
382
382
Py_DECREF (builtins );
383
+ /* Clear module dict copies stored in the interpreter state */
384
+ _PyState_ClearModules ();
383
385
/* Collect references */
384
386
_PyGC_CollectNoFail ();
385
387
/* Dump GC stats before it's too late, since it uses the warnings
Original file line number Diff line number Diff line change @@ -320,6 +320,31 @@ PyState_RemoveModule(struct PyModuleDef* def)
320
320
return PyList_SetItem (state -> modules_by_index , index , Py_None );
321
321
}
322
322
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
+
323
348
void
324
349
PyThreadState_Clear (PyThreadState * tstate )
325
350
{
You can’t perform that action at this time.
0 commit comments