mirror of
https://github.com/python/cpython.git
synced 2025-08-30 13:38:43 +00:00
Two more refinements of the cleanup process.
(1) Explicitly clear __builtin__._ and sys.{last,exc}_* before clearing anything else. These are common places where user values hide and people complain when their destructors fail. Since the modules containing them are deleted *last* of all, they would come too late in the normal destruction order. Sigh. (2) Add some debugging aid to cleanup (after a suggestion by Marc Lemburg) -- print the names of the modules being cleaned, and (when -vv is used) print the names of the variables being cleared.
This commit is contained in:
parent
8ee4a60c70
commit
a0fec2b5df
1 changed files with 52 additions and 3 deletions
|
@ -148,20 +148,26 @@ clear_carefully(d)
|
||||||
while (PyDict_Next(d, &pos, &key, &value)) {
|
while (PyDict_Next(d, &pos, &key, &value)) {
|
||||||
if (value != Py_None && PyString_Check(key)) {
|
if (value != Py_None && PyString_Check(key)) {
|
||||||
char *s = PyString_AsString(key);
|
char *s = PyString_AsString(key);
|
||||||
if (s[0] == '_' && s[1] != '_')
|
if (s[0] == '_' && s[1] != '_') {
|
||||||
|
if (Py_VerboseFlag > 1)
|
||||||
|
fprintf(stderr, "# clear[1] %s\n", s);
|
||||||
PyDict_SetItem(d, key, Py_None);
|
PyDict_SetItem(d, key, Py_None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Next, clear all names except those starting with two underscores */
|
/* Next, clear all names except those starting with two underscores */
|
||||||
pos = 0;
|
pos = 0;
|
||||||
while (PyDict_Next(d, &pos, &key, &value)) {
|
while (PyDict_Next(d, &pos, &key, &value)) {
|
||||||
if (value != Py_None && PyString_Check(key)) {
|
if (value != Py_None && PyString_Check(key)) {
|
||||||
char *s = PyString_AsString(key);
|
char *s = PyString_AsString(key);
|
||||||
if (s[0] != '_' || s[1] != '_')
|
if (s[0] != '_' || s[1] != '_') {
|
||||||
|
if (Py_VerboseFlag > 1)
|
||||||
|
fprintf(stderr, "# clear[2] %s\n", s);
|
||||||
PyDict_SetItem(d, key, Py_None);
|
PyDict_SetItem(d, key, Py_None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PyDict_Clear(d); /* Finally, clear all names */
|
PyDict_Clear(d); /* Finally, clear all names */
|
||||||
|
|
||||||
|
@ -169,6 +175,14 @@ clear_carefully(d)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* List of names to clear in sys */
|
||||||
|
static char* sys_deletes[] = {
|
||||||
|
"exc_type", "exc_value", "exc_traceback",
|
||||||
|
"last_type", "last_value", "last_traceback",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Un-initialize things, as good as we can */
|
/* Un-initialize things, as good as we can */
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -183,6 +197,30 @@ PyImport_Cleanup()
|
||||||
if (modules == NULL)
|
if (modules == NULL)
|
||||||
return; /* Already done */
|
return; /* Already done */
|
||||||
|
|
||||||
|
/* Delete some special variables first. These are common
|
||||||
|
places where user values hide and people complain when their
|
||||||
|
destructors fail. Since the modules containing them are
|
||||||
|
deleted *last* of all, they would come too late in the normal
|
||||||
|
destruction order. Sigh. */
|
||||||
|
|
||||||
|
value = PyDict_GetItemString(modules, "__builtin__");
|
||||||
|
if (value != NULL && PyModule_Check(value)) {
|
||||||
|
dict = PyModule_GetDict(value);
|
||||||
|
if (Py_VerboseFlag)
|
||||||
|
fprintf(stderr, "# clear __builtin__._\n");
|
||||||
|
PyDict_SetItemString(dict, "_", Py_None);
|
||||||
|
}
|
||||||
|
value = PyDict_GetItemString(modules, "sys");
|
||||||
|
if (value != NULL && PyModule_Check(value)) {
|
||||||
|
char **p;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* The special treatment of __builtin__ here is because even
|
/* The special treatment of __builtin__ here is because even
|
||||||
when it's not referenced as a module, its dictionary is
|
when it's not referenced as a module, its dictionary is
|
||||||
referenced by almost every module's __builtins__. Since
|
referenced by almost every module's __builtins__. Since
|
||||||
|
@ -212,6 +250,9 @@ PyImport_Cleanup()
|
||||||
continue;
|
continue;
|
||||||
if (strcmp(name, "sys") == 0)
|
if (strcmp(name, "sys") == 0)
|
||||||
continue;
|
continue;
|
||||||
|
if (Py_VerboseFlag)
|
||||||
|
fprintf(stderr,
|
||||||
|
"# cleanup[1] %s\n", name);
|
||||||
clear_carefully(dict);
|
clear_carefully(dict);
|
||||||
PyDict_SetItem(modules, key, Py_None);
|
PyDict_SetItem(modules, key, Py_None);
|
||||||
ndone++;
|
ndone++;
|
||||||
|
@ -223,6 +264,8 @@ PyImport_Cleanup()
|
||||||
value = PyDict_GetItemString(modules, "__main__");
|
value = PyDict_GetItemString(modules, "__main__");
|
||||||
if (value != NULL && PyModule_Check(value)) {
|
if (value != NULL && PyModule_Check(value)) {
|
||||||
dict = PyModule_GetDict(value);
|
dict = PyModule_GetDict(value);
|
||||||
|
if (Py_VerboseFlag)
|
||||||
|
fprintf(stderr, "# cleanup __main__\n");
|
||||||
clear_carefully(dict);
|
clear_carefully(dict);
|
||||||
PyDict_SetItemString(modules, "__main__", Py_None);
|
PyDict_SetItemString(modules, "__main__", Py_None);
|
||||||
}
|
}
|
||||||
|
@ -237,6 +280,8 @@ PyImport_Cleanup()
|
||||||
continue;
|
continue;
|
||||||
if (strcmp(name, "sys") == 0)
|
if (strcmp(name, "sys") == 0)
|
||||||
continue;
|
continue;
|
||||||
|
if (Py_VerboseFlag)
|
||||||
|
fprintf(stderr, "# cleanup[2] %s\n", name);
|
||||||
clear_carefully(dict);
|
clear_carefully(dict);
|
||||||
PyDict_SetItem(modules, key, Py_None);
|
PyDict_SetItem(modules, key, Py_None);
|
||||||
}
|
}
|
||||||
|
@ -246,13 +291,17 @@ PyImport_Cleanup()
|
||||||
value = PyDict_GetItemString(modules, "sys");
|
value = PyDict_GetItemString(modules, "sys");
|
||||||
if (value != NULL && PyModule_Check(value)) {
|
if (value != NULL && PyModule_Check(value)) {
|
||||||
dict = PyModule_GetDict(value);
|
dict = PyModule_GetDict(value);
|
||||||
|
if (Py_VerboseFlag)
|
||||||
|
fprintf(stderr, "# cleanup sys\n");
|
||||||
clear_carefully(dict);
|
clear_carefully(dict);
|
||||||
PyDict_SetItemString(modules, "sys", Py_None);
|
PyDict_SetItemString(modules, "sys", Py_None);
|
||||||
}
|
}
|
||||||
value = PyDict_GetItemString(modules, "__builtin__");
|
value = PyDict_GetItemString(modules, "__builtin__");
|
||||||
if (value != NULL && PyModule_Check(value)) {
|
if (value != NULL && PyModule_Check(value)) {
|
||||||
dict = PyModule_GetDict(value);
|
dict = PyModule_GetDict(value);
|
||||||
clear_carefully(dict);
|
if (Py_VerboseFlag)
|
||||||
|
fprintf(stderr, "# cleanup __builtin__\n");
|
||||||
|
clear_carefully(dict); /* XXX Is this necessary? */
|
||||||
PyDict_SetItemString(modules, "__builtin__", Py_None);
|
PyDict_SetItemString(modules, "__builtin__", Py_None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue