Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 05f9dce

Browse files
committed
Moved clear_carefully() to _PyModule_Clear() in moduleobject.c
(modified) and use that. Some differences in the cleanup algorithm: - Clear __main__ before the other modules. - Delete more sys variables: including ps1, ps2, exitfunc, argv, and even path -- this will prevent new imports! - Restore stdin, stdout, stderr from __stdin__, __stdout__, __stderr__, effectively deleting hooks that the user might have installed -- so their (the hooks') destructors will run.
1 parent bd36dba commit 05f9dce

1 file changed

Lines changed: 31 additions & 69 deletions

File tree

Python/import.c

Lines changed: 31 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -125,63 +125,21 @@ PyImport_GetModuleDict()
125125
}
126126

127127

128-
/* Helper for PyImport_Cleanup */
129-
130-
static void
131-
clear_carefully(d)
132-
PyObject *d;
133-
{
134-
/* To make the execution order of destructors for global
135-
objects a bit more predictable, we first zap all objects
136-
whose name starts with a single underscore, before we clear
137-
the entire dictionary. We zap them by replacing them with
138-
None, rather than deleting them from the dictionary, to
139-
avoid rehashing the dictionary (to some extent). */
140-
141-
int pos;
142-
PyObject *key, *value;
143-
144-
Py_INCREF(d); /* Prevent it from being deleted recursively */
145-
146-
/* First, clear only names starting with a single underscore */
147-
pos = 0;
148-
while (PyDict_Next(d, &pos, &key, &value)) {
149-
if (value != Py_None && PyString_Check(key)) {
150-
char *s = PyString_AsString(key);
151-
if (s[0] == '_' && s[1] != '_') {
152-
if (Py_VerboseFlag > 1)
153-
fprintf(stderr, "# clear[1] %s\n", s);
154-
PyDict_SetItem(d, key, Py_None);
155-
}
156-
}
157-
}
158-
159-
/* Next, clear all names except those starting with two underscores */
160-
pos = 0;
161-
while (PyDict_Next(d, &pos, &key, &value)) {
162-
if (value != Py_None && PyString_Check(key)) {
163-
char *s = PyString_AsString(key);
164-
if (s[0] != '_' || s[1] != '_') {
165-
if (Py_VerboseFlag > 1)
166-
fprintf(stderr, "# clear[2] %s\n", s);
167-
PyDict_SetItem(d, key, Py_None);
168-
}
169-
}
170-
}
171-
172-
PyDict_Clear(d); /* Finally, clear all names */
173-
174-
Py_DECREF(d); /* Match INCREF at top */
175-
}
176-
177-
178128
/* List of names to clear in sys */
179129
static char* sys_deletes[] = {
130+
"path", "argv", "ps1", "ps2", "exitfunc",
180131
"exc_type", "exc_value", "exc_traceback",
181132
"last_type", "last_value", "last_traceback",
182133
NULL
183134
};
184135

136+
static char* sys_files[] = {
137+
"stdin", "__stdin__",
138+
"stdout", "__stdout__",
139+
"stderr", "__stderr__",
140+
NULL
141+
};
142+
185143

186144
/* Un-initialize things, as good as we can */
187145

@@ -213,12 +171,30 @@ PyImport_Cleanup()
213171
value = PyDict_GetItemString(modules, "sys");
214172
if (value != NULL && PyModule_Check(value)) {
215173
char **p;
174+
PyObject *v;
216175
dict = PyModule_GetDict(value);
217176
for (p = sys_deletes; *p != NULL; p++) {
218177
if (Py_VerboseFlag)
219178
fprintf(stderr, "# clear sys.%s\n", *p);
220179
PyDict_SetItemString(dict, *p, Py_None);
221180
}
181+
for (p = sys_files; *p != NULL; p+=2) {
182+
if (Py_VerboseFlag)
183+
fprintf(stderr, "# restore sys.%s\n", *p);
184+
v = PyDict_GetItemString(dict, *(p+1));
185+
if (v == NULL)
186+
v = Py_None;
187+
PyDict_SetItemString(dict, *p, v);
188+
}
189+
}
190+
191+
/* First, delete __main__ */
192+
value = PyDict_GetItemString(modules, "__main__");
193+
if (value != NULL && PyModule_Check(value)) {
194+
if (Py_VerboseFlag)
195+
fprintf(stderr, "# cleanup __main__\n");
196+
_PyModule_Clear(value);
197+
PyDict_SetItemString(modules, "__main__", Py_None);
222198
}
223199

224200
/* The special treatment of __builtin__ here is because even
@@ -235,7 +211,7 @@ PyImport_Cleanup()
235211
also marks them as "non existent" so they won't be
236212
re-imported. */
237213

238-
/* First, repeatedly delete modules with a reference count of
214+
/* Next, repeatedly delete modules with a reference count of
239215
one (skipping __builtin__ and sys) and delete them */
240216
do {
241217
ndone = 0;
@@ -245,63 +221,49 @@ PyImport_Cleanup()
245221
continue;
246222
if (PyModule_Check(value)) {
247223
name = PyString_AsString(key);
248-
dict = PyModule_GetDict(value);
249224
if (strcmp(name, "__builtin__") == 0)
250225
continue;
251226
if (strcmp(name, "sys") == 0)
252227
continue;
253228
if (Py_VerboseFlag)
254229
fprintf(stderr,
255230
"# cleanup[1] %s\n", name);
256-
clear_carefully(dict);
231+
_PyModule_Clear(value);
257232
PyDict_SetItem(modules, key, Py_None);
258233
ndone++;
259234
}
260235
}
261236
} while (ndone > 0);
262237

263-
/* Next, delete __main__ if it's still there */
264-
value = PyDict_GetItemString(modules, "__main__");
265-
if (value != NULL && PyModule_Check(value)) {
266-
dict = PyModule_GetDict(value);
267-
if (Py_VerboseFlag)
268-
fprintf(stderr, "# cleanup __main__\n");
269-
clear_carefully(dict);
270-
PyDict_SetItemString(modules, "__main__", Py_None);
271-
}
272-
273238
/* Next, delete all modules (still skipping __builtin__ and sys) */
274239
pos = 0;
275240
while (PyDict_Next(modules, &pos, &key, &value)) {
276241
if (PyModule_Check(value)) {
277242
name = PyString_AsString(key);
278-
dict = PyModule_GetDict(value);
279243
if (strcmp(name, "__builtin__") == 0)
280244
continue;
281245
if (strcmp(name, "sys") == 0)
282246
continue;
283247
if (Py_VerboseFlag)
284248
fprintf(stderr, "# cleanup[2] %s\n", name);
285-
clear_carefully(dict);
249+
_PyModule_Clear(value);
286250
PyDict_SetItem(modules, key, Py_None);
287251
}
288252
}
289253

290254
/* Next, delete sys and __builtin__ (in that order) */
291255
value = PyDict_GetItemString(modules, "sys");
292256
if (value != NULL && PyModule_Check(value)) {
293-
dict = PyModule_GetDict(value);
294257
if (Py_VerboseFlag)
295258
fprintf(stderr, "# cleanup sys\n");
296-
clear_carefully(dict);
259+
_PyModule_Clear(value);
297260
PyDict_SetItemString(modules, "sys", Py_None);
298261
}
299262
value = PyDict_GetItemString(modules, "__builtin__");
300263
if (value != NULL && PyModule_Check(value)) {
301-
dict = PyModule_GetDict(value);
302264
if (Py_VerboseFlag)
303265
fprintf(stderr, "# cleanup __builtin__\n");
304-
clear_carefully(dict); /* XXX Is this necessary? */
266+
_PyModule_Clear(value);
305267
PyDict_SetItemString(modules, "__builtin__", Py_None);
306268
}
307269

0 commit comments

Comments
 (0)