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:
Guido van Rossum 1998-02-19 20:51:52 +00:00
parent c83db33781
commit f1dc0615e9
2 changed files with 51 additions and 1 deletions

View File

@ -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
} }

View File

@ -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);