summaryrefslogtreecommitdiff
path: root/Objects/moduleobject.c
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1998-02-19 20:51:52 +0000
committerGuido van Rossum <guido@python.org>1998-02-19 20:51:52 +0000
commitbd446962924feaed73c11b68fd4b1c1656679dad (patch)
tree22002af93768efe5dc108eec89e0a0aeda00030d /Objects/moduleobject.c
parente8ea7f5e2fe26d09f3ebd347df2214481df5f45c (diff)
downloadcpython-bd446962924feaed73c11b68fd4b1c1656679dad.tar.gz
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).
Diffstat (limited to 'Objects/moduleobject.c')
-rw-r--r--Objects/moduleobject.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c
index 1ba1a1b705..7a41439360 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -93,6 +93,55 @@ PyModule_GetName(m)
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 */
static void
@@ -100,7 +149,7 @@ module_dealloc(m)
PyModuleObject *m;
{
if (m->md_dict != NULL) {
- PyDict_Clear(m->md_dict);
+ _PyModule_Clear((PyObject *)m);
Py_DECREF(m->md_dict);
}
free((char *)m);