mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +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,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); | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Guido van Rossum
						Guido van Rossum