diff options
author | Guido van Rossum <guido@python.org> | 1998-02-19 20:51:52 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1998-02-19 20:51:52 (GMT) |
commit | f1dc0615e913fd0028a2fa6fda9607b3edfa76d5 (patch) | |
tree | f2d858ecea20146e601215cf16d4072c32765720 | |
parent | c83db33781d9333581f90c1f427b2c64c4e7c0d8 (diff) | |
download | cpython-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.h | 1 | ||||
-rw-r--r-- | Objects/moduleobject.c | 51 |
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); |