Commit a2376b8e authored by Guido van Rossum's avatar Guido van Rossum

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.
parent 14c51284
......@@ -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);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment