]> granicus.if.org Git - python/commitdiff
Add internal routine _PyModule_Clear(), which does approximately what
authorGuido van Rossum <guido@python.org>
Thu, 19 Feb 1998 20:51:52 +0000 (20:51 +0000)
committerGuido van Rossum <guido@python.org>
Thu, 19 Feb 1998 20:51:52 +0000 (20:51 +0000)
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).

Include/moduleobject.h
Objects/moduleobject.c

index a435b7f54d164c7cfadcf19b716e72b6ce9b86fa..03bc9f7b73c624e82a916d7dee34c503377c621a 100644 (file)
@@ -44,6 +44,7 @@ extern DL_IMPORT(PyTypeObject) PyModule_Type;
 extern PyObject *PyModule_New Py_PROTO((char *));
 extern PyObject *PyModule_GetDict Py_PROTO((PyObject *));
 extern char *PyModule_GetName Py_PROTO((PyObject *));
+extern void _PyModule_Clear Py_PROTO((PyObject *));
 
 #ifdef __cplusplus
 }
index 1ba1a1b7056fc73826847cd4d2d61145a1938a7c..7a41439360d67ed76fd855c0dcf9768a3ea4cc57 100644 (file)
@@ -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);