summaryrefslogtreecommitdiffstats
path: root/Python/import.c
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1998-02-19 20:58:44 (GMT)
committerGuido van Rossum <guido@python.org>1998-02-19 20:58:44 (GMT)
commit05f9dce34f3a91e1a9d69e3e85c93c506e0cc6ba (patch)
treebb7c62cd1102037ed02bb70378e5616cf98bb210 /Python/import.c
parentbd36dbaaa53929e1bd8609e734c7a0fa128b7bd2 (diff)
downloadcpython-05f9dce34f3a91e1a9d69e3e85c93c506e0cc6ba.zip
cpython-05f9dce34f3a91e1a9d69e3e85c93c506e0cc6ba.tar.gz
cpython-05f9dce34f3a91e1a9d69e3e85c93c506e0cc6ba.tar.bz2
Moved clear_carefully() to _PyModule_Clear() in moduleobject.c
(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.
Diffstat (limited to 'Python/import.c')
-rw-r--r--Python/import.c100
1 files changed, 31 insertions, 69 deletions
diff --git a/Python/import.c b/Python/import.c
index fd92698..3aa110c 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -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);
}