mirror of https://github.com/python/cpython
Add internal routine _PyModule_Clear(), which does approximately what
clear_carefully() used to do in import.c. Differences: leave only __builtins__ alone in the 2nd pass; and don't clear the dictionary (on the theory that as long as there are references left to the dictionary, those might be destructors that might expect __builtins__ to be alive when they run; and __builtins__ can't normally be part of a cycle).
This commit is contained in:
parent
c83db33781
commit
f1dc0615e9
|
@ -44,6 +44,7 @@ extern DL_IMPORT(PyTypeObject) PyModule_Type;
|
||||||
extern PyObject *PyModule_New Py_PROTO((char *));
|
extern PyObject *PyModule_New Py_PROTO((char *));
|
||||||
extern PyObject *PyModule_GetDict Py_PROTO((PyObject *));
|
extern PyObject *PyModule_GetDict Py_PROTO((PyObject *));
|
||||||
extern char *PyModule_GetName Py_PROTO((PyObject *));
|
extern char *PyModule_GetName Py_PROTO((PyObject *));
|
||||||
|
extern void _PyModule_Clear Py_PROTO((PyObject *));
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,6 +93,55 @@ PyModule_GetName(m)
|
||||||
return PyString_AsString(nameobj);
|
return PyString_AsString(nameobj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_PyModule_Clear(m)
|
||||||
|
PyObject *m;
|
||||||
|
{
|
||||||
|
/* To make the execution order of destructors for global
|
||||||
|
objects a bit more predictable, we first zap all objects
|
||||||
|
whose name starts with a single underscore, before we clear
|
||||||
|
the entire dictionary. We zap them by replacing them with
|
||||||
|
None, rather than deleting them from the dictionary, to
|
||||||
|
avoid rehashing the dictionary (to some extent). */
|
||||||
|
|
||||||
|
int pos;
|
||||||
|
PyObject *key, *value;
|
||||||
|
PyObject *d;
|
||||||
|
|
||||||
|
d = ((PyModuleObject *)m)->md_dict;
|
||||||
|
|
||||||
|
/* First, clear only names starting with a single underscore */
|
||||||
|
pos = 0;
|
||||||
|
while (PyDict_Next(d, &pos, &key, &value)) {
|
||||||
|
if (value != Py_None && PyString_Check(key)) {
|
||||||
|
char *s = PyString_AsString(key);
|
||||||
|
if (s[0] == '_' && s[1] != '_') {
|
||||||
|
if (Py_VerboseFlag > 1)
|
||||||
|
fprintf(stderr, "# clear[1] %s\n", s);
|
||||||
|
PyDict_SetItem(d, key, Py_None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next, clear all names except for __builtins__ */
|
||||||
|
pos = 0;
|
||||||
|
while (PyDict_Next(d, &pos, &key, &value)) {
|
||||||
|
if (value != Py_None && PyString_Check(key)) {
|
||||||
|
char *s = PyString_AsString(key);
|
||||||
|
if (s[0] != '_' || strcmp(s, "__builtins__") != 0) {
|
||||||
|
if (Py_VerboseFlag > 1)
|
||||||
|
fprintf(stderr, "# clear[2] %s\n", s);
|
||||||
|
PyDict_SetItem(d, key, Py_None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note: we leave __builtins__ in place, so that destructors
|
||||||
|
of non-global objects defined in this module can still use
|
||||||
|
builtins, in particularly 'None'. */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Methods */
|
/* Methods */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -100,7 +149,7 @@ module_dealloc(m)
|
||||||
PyModuleObject *m;
|
PyModuleObject *m;
|
||||||
{
|
{
|
||||||
if (m->md_dict != NULL) {
|
if (m->md_dict != NULL) {
|
||||||
PyDict_Clear(m->md_dict);
|
_PyModule_Clear((PyObject *)m);
|
||||||
Py_DECREF(m->md_dict);
|
Py_DECREF(m->md_dict);
|
||||||
}
|
}
|
||||||
free((char *)m);
|
free((char *)m);
|
||||||
|
|
Loading…
Reference in New Issue