]> granicus.if.org Git - python/commitdiff
Moved clear_carefully() to _PyModule_Clear() in moduleobject.c
authorGuido van Rossum <guido@python.org>
Thu, 19 Feb 1998 20:58:44 +0000 (20:58 +0000)
committerGuido van Rossum <guido@python.org>
Thu, 19 Feb 1998 20:58:44 +0000 (20:58 +0000)
(modified) and use that.

Some differences in the cleanup algorithm:

- Clear __main__ before the other modules.

- Delete more sys variables: including ps1, ps2, exitfunc, argv, and
even path -- this will prevent new imports!

- Restore stdin, stdout, stderr from __stdin__, __stdout__,
__stderr__, effectively deleting hooks that the user might have
installed -- so their (the hooks') destructors will run.

Python/import.c

index fd92698d44a03eef0c7d172c3798b110c2ee5032..3aa110c35bdabb11fa467f0225cd96c5fde01276 100644 (file)
@@ -125,63 +125,21 @@ PyImport_GetModuleDict()
 }
 
 
-/* Helper for PyImport_Cleanup */
-
-static void
-clear_carefully(d)
-       PyObject *d;
-{
-       /* 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;
-
-       Py_INCREF(d); /* Prevent it from being deleted recursively */
-
-       /* 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 those starting with two underscores */
-       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[2] %s\n", s);
-                               PyDict_SetItem(d, key, Py_None);
-                       }
-               }
-       }
-
-       PyDict_Clear(d); /* Finally, clear all names */
-
-       Py_DECREF(d); /* Match INCREF at top */
-}
-
-
 /* List of names to clear in sys */
 static char* sys_deletes[] = {
+       "path", "argv", "ps1", "ps2", "exitfunc",
        "exc_type", "exc_value", "exc_traceback",
        "last_type", "last_value", "last_traceback",
        NULL
 };
 
+static char* sys_files[] = {
+       "stdin", "__stdin__",
+       "stdout", "__stdout__",
+       "stderr", "__stderr__",
+       NULL
+};
+
 
 /* Un-initialize things, as good as we can */
 
@@ -213,12 +171,30 @@ PyImport_Cleanup()
        value = PyDict_GetItemString(modules, "sys");
        if (value != NULL && PyModule_Check(value)) {
                char **p;
+               PyObject *v;
                dict = PyModule_GetDict(value);
                for (p = sys_deletes; *p != NULL; p++) {
                        if (Py_VerboseFlag)
                                fprintf(stderr, "# clear sys.%s\n", *p);
                        PyDict_SetItemString(dict, *p, Py_None);
                }
+               for (p = sys_files; *p != NULL; p+=2) {
+                       if (Py_VerboseFlag)
+                               fprintf(stderr, "# restore sys.%s\n", *p);
+                       v = PyDict_GetItemString(dict, *(p+1));
+                       if (v == NULL)
+                               v = Py_None;
+                       PyDict_SetItemString(dict, *p, v);
+               }
+       }
+
+       /* First, delete __main__ */
+       value = PyDict_GetItemString(modules, "__main__");
+       if (value != NULL && PyModule_Check(value)) {
+               if (Py_VerboseFlag)
+                       fprintf(stderr, "# cleanup __main__\n");
+               _PyModule_Clear(value);
+               PyDict_SetItemString(modules, "__main__", Py_None);
        }
 
        /* The special treatment of __builtin__ here is because even
@@ -235,7 +211,7 @@ PyImport_Cleanup()
           also marks them as "non existent" so they won't be
           re-imported. */
 
-       /* First, repeatedly delete modules with a reference count of
+       /* Next, repeatedly delete modules with a reference count of
           one (skipping __builtin__ and sys) and delete them */
        do {
                ndone = 0;
@@ -245,7 +221,6 @@ PyImport_Cleanup()
                                continue;
                        if (PyModule_Check(value)) {
                                name = PyString_AsString(key);
-                               dict = PyModule_GetDict(value);
                                if (strcmp(name, "__builtin__") == 0)
                                        continue;
                                if (strcmp(name, "sys") == 0)
@@ -253,36 +228,25 @@ PyImport_Cleanup()
                                if (Py_VerboseFlag)
                                        fprintf(stderr,
                                                "# cleanup[1] %s\n", name);
-                               clear_carefully(dict);
+                               _PyModule_Clear(value);
                                PyDict_SetItem(modules, key, Py_None);
                                ndone++;
                        }
                }
        } while (ndone > 0);
 
-       /* Next, delete __main__ if it's still there */
-       value = PyDict_GetItemString(modules, "__main__");
-       if (value != NULL && PyModule_Check(value)) {
-               dict = PyModule_GetDict(value);
-               if (Py_VerboseFlag)
-                       fprintf(stderr, "# cleanup __main__\n");
-               clear_carefully(dict);
-               PyDict_SetItemString(modules, "__main__", Py_None);
-       }
-
        /* Next, delete all modules (still skipping __builtin__ and sys) */
        pos = 0;
        while (PyDict_Next(modules, &pos, &key, &value)) {
                if (PyModule_Check(value)) {
                        name = PyString_AsString(key);
-                       dict = PyModule_GetDict(value);
                        if (strcmp(name, "__builtin__") == 0)
                                continue;
                        if (strcmp(name, "sys") == 0)
                                continue;
                        if (Py_VerboseFlag)
                                fprintf(stderr, "# cleanup[2] %s\n", name);
-                       clear_carefully(dict);
+                       _PyModule_Clear(value);
                        PyDict_SetItem(modules, key, Py_None);
                }
        }
@@ -290,18 +254,16 @@ PyImport_Cleanup()
        /* Next, delete sys and __builtin__ (in that order) */
        value = PyDict_GetItemString(modules, "sys");
        if (value != NULL && PyModule_Check(value)) {
-               dict = PyModule_GetDict(value);
                if (Py_VerboseFlag)
                        fprintf(stderr, "# cleanup sys\n");
-               clear_carefully(dict);
+               _PyModule_Clear(value);
                PyDict_SetItemString(modules, "sys", Py_None);
        }
        value = PyDict_GetItemString(modules, "__builtin__");
        if (value != NULL && PyModule_Check(value)) {
-               dict = PyModule_GetDict(value);
                if (Py_VerboseFlag)
                        fprintf(stderr, "# cleanup __builtin__\n");
-               clear_carefully(dict); /* XXX Is this necessary? */
+               _PyModule_Clear(value);
                PyDict_SetItemString(modules, "__builtin__", Py_None);
        }