summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1998-02-19 20:51:52 (GMT)
committerGuido van Rossum <guido@python.org>1998-02-19 20:51:52 (GMT)
commitf1dc0615e913fd0028a2fa6fda9607b3edfa76d5 (patch)
treef2d858ecea20146e601215cf16d4072c32765720
parentc83db33781d9333581f90c1f427b2c64c4e7c0d8 (diff)
downloadcpython-f1dc0615e913fd0028a2fa6fda9607b3edfa76d5.zip
cpython-f1dc0615e913fd0028a2fa6fda9607b3edfa76d5.tar.gz
cpython-f1dc0615e913fd0028a2fa6fda9607b3edfa76d5.tar.bz2
Add internal routine _PyModule_Clear(), which does approximately what
clear_carefully() used to do in import.c. Differences: leave only __builtins__ alone in the 2nd pass; and don't clear the dictionary (on the theory that as long as there are references left to the dictionary, those might be destructors that might expect __builtins__ to be alive when they run; and __builtins__ can't normally be part of a cycle).
-rw-r--r--Include/moduleobject.h1
-rw-r--r--Objects/moduleobject.c51
2 files changed, 51 insertions, 1 deletions
diff --git a/Include/moduleobject.h b/Include/moduleobject.h
index a435b7f..03bc9f7 100644
--- a/Include/moduleobject.h
+++ b/Include/moduleobject.h
@@ -44,6 +44,7 @@ extern DL_IMPORT(PyTypeObject) PyModule_Type;
extern PyObject *PyModule_New Py_PROTO((char *));
extern PyObject *PyModule_GetDict Py_PROTO((PyObject *));
extern char *PyModule_GetName Py_PROTO((PyObject *));
+extern void _PyModule_Clear Py_PROTO((PyObject *));
#ifdef __cplusplus
}
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c
index 1ba1a1b..7a41439 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -93,6 +93,55 @@ PyModule_GetName(m)
return PyString_AsString(nameobj);
}
+void
+_PyModule_Clear(m)
+ PyObject *m;
+{
+ /* 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;
+ PyObject *d;
+
+ d = ((PyModuleObject *)m)->md_dict;
+
+ /* 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 for __builtins__ */
+ pos = 0;
+ while (PyDict_Next(d, &pos, &key, &value)) {
+ if (value != Py_None && PyString_Check(key)) {
+ char *s = PyString_AsString(key);
+ if (s[0] != '_' || strcmp(s, "__builtins__") != 0) {
+ if (Py_VerboseFlag > 1)
+ fprintf(stderr, "# clear[2] %s\n", s);
+ PyDict_SetItem(d, key, Py_None);
+ }
+ }
+ }
+
+ /* Note: we leave __builtins__ in place, so that destructors
+ of non-global objects defined in this module can still use
+ builtins, in particularly 'None'. */
+
+}
+
/* Methods */
static void
@@ -100,7 +149,7 @@ module_dealloc(m)
PyModuleObject *m;
{
if (m->md_dict != NULL) {
- PyDict_Clear(m->md_dict);
+ _PyModule_Clear((PyObject *)m);
Py_DECREF(m->md_dict);
}
free((char *)m);