From a0fec2b5df6827300bf80511a1fd6596e6f71e21 Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Fri, 6 Feb 1998 17:16:02 +0000 Subject: [PATCH] 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. --- Python/import.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/Python/import.c b/Python/import.c index 224a3bcb08..9dbbd255b6 100644 --- a/Python/import.c +++ b/Python/import.c @@ -148,8 +148,11 @@ clear_carefully(d) 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 (s[0] == '_' && s[1] != '_') { + if (Py_VerboseFlag > 1) + fprintf(stderr, "# clear[1] %s\n", s); PyDict_SetItem(d, key, Py_None); + } } } @@ -158,8 +161,11 @@ clear_carefully(d) 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 (s[0] != '_' || s[1] != '_') { + if (Py_VerboseFlag > 1) + fprintf(stderr, "# clear[2] %s\n", s); PyDict_SetItem(d, key, Py_None); + } } } @@ -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 */ void @@ -183,6 +197,30 @@ PyImport_Cleanup() if (modules == NULL) 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 when it's not referenced as a module, its dictionary is referenced by almost every module's __builtins__. Since @@ -212,6 +250,9 @@ PyImport_Cleanup() continue; if (strcmp(name, "sys") == 0) continue; + if (Py_VerboseFlag) + fprintf(stderr, + "# cleanup[1] %s\n", name); clear_carefully(dict); PyDict_SetItem(modules, key, Py_None); ndone++; @@ -223,6 +264,8 @@ PyImport_Cleanup() 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); } @@ -237,6 +280,8 @@ PyImport_Cleanup() continue; if (strcmp(name, "sys") == 0) continue; + if (Py_VerboseFlag) + fprintf(stderr, "# cleanup[2] %s\n", name); clear_carefully(dict); PyDict_SetItem(modules, key, Py_None); } @@ -246,13 +291,17 @@ PyImport_Cleanup() 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); PyDict_SetItemString(modules, "sys", Py_None); } value = PyDict_GetItemString(modules, "__builtin__"); if (value != NULL && PyModule_Check(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); } -- 2.40.0