summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCollin Winter <collinw@gmail.com>2007-03-12 16:49:23 (GMT)
committerCollin Winter <collinw@gmail.com>2007-03-12 16:49:23 (GMT)
commite19d7a3c0ac25680d2f72669f1441dadbb2f9a41 (patch)
tree85bd8be0b7673cd915fad4c782a5d3305062b77c
parent1817f096f4153293abe7ffb6eda47be3f809fa77 (diff)
downloadcpython-e19d7a3c0ac25680d2f72669f1441dadbb2f9a41.zip
cpython-e19d7a3c0ac25680d2f72669f1441dadbb2f9a41.tar.gz
cpython-e19d7a3c0ac25680d2f72669f1441dadbb2f9a41.tar.bz2
Bug #742342: make Python stop segfaulting on infinitely-recursive reload()s. Fixed by patch #922167.
Backported from r54291.
-rw-r--r--Include/pystate.h1
-rw-r--r--Lib/test/infinite_reload.py7
-rw-r--r--Lib/test/test_import.py12
-rw-r--r--Misc/NEWS3
-rw-r--r--Python/import.c37
-rw-r--r--Python/pystate.c2
-rw-r--r--Python/pythonrun.c4
7 files changed, 64 insertions, 2 deletions
diff --git a/Include/pystate.h b/Include/pystate.h
index cf29695..4919d99 100644
--- a/Include/pystate.h
+++ b/Include/pystate.h
@@ -21,6 +21,7 @@ typedef struct _is {
PyObject *modules;
PyObject *sysdict;
PyObject *builtins;
+ PyObject *modules_reloading;
PyObject *codec_search_path;
PyObject *codec_search_cache;
diff --git a/Lib/test/infinite_reload.py b/Lib/test/infinite_reload.py
new file mode 100644
index 0000000..bfbec91
--- /dev/null
+++ b/Lib/test/infinite_reload.py
@@ -0,0 +1,7 @@
+# For testing http://python.org/sf/742342, which reports that Python
+# segfaults (infinite recursion in C) in the presence of infinite
+# reload()ing. This module is imported by test_import.py:test_infinite_reload
+# to make sure this doesn't happen any more.
+
+import infinite_reload
+reload(infinite_reload)
diff --git a/Lib/test/test_import.py b/Lib/test/test_import.py
index effba3c..ed97f84 100644
--- a/Lib/test/test_import.py
+++ b/Lib/test/test_import.py
@@ -222,3 +222,15 @@ def test_import_initless_directory_warning():
warnings.filters = oldfilters
test_import_initless_directory_warning()
+
+def test_infinite_reload():
+ # Bug #742342 reports that Python segfaults (infinite recursion in C)
+ # when faced with self-recursive reload()ing.
+
+ sys.path.insert(0, os.path.dirname(__file__))
+ try:
+ import infinite_reload
+ finally:
+ sys.path.pop(0)
+
+test_infinite_reload()
diff --git a/Misc/NEWS b/Misc/NEWS
index dc981ff..c21972d 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 2.5.1c1?
Core and builtins
-----------------
+- Patch #922167: Python no longer segfaults when faced with infinitely
+ self-recursive reload() calls (as reported by bug #742342).
+
- Patch #1675981: remove unreachable code from ``type.__new__()`` method.
- Patch #1638879: don't accept strings with embedded NUL bytes in long().
diff --git a/Python/import.c b/Python/import.c
index 390f9e3..b62eeef 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -339,6 +339,25 @@ imp_release_lock(PyObject *self, PyObject *noargs)
return Py_None;
}
+PyObject *
+PyImport_GetModulesReloading(void)
+{
+ PyInterpreterState *interp = PyThreadState_Get()->interp;
+ if (interp->modules_reloading == NULL)
+ Py_FatalError("PyImport_GetModuleDict: no modules_reloading dictionary!");
+ return interp->modules_reloading;
+}
+
+static void
+imp_modules_reloading_clear (void)
+{
+ PyInterpreterState *interp = PyThreadState_Get()->interp;
+ if (interp->modules_reloading == NULL)
+ return;
+ PyDict_Clear(interp->modules_reloading);
+ return;
+}
+
/* Helper for sys */
PyObject *
@@ -498,6 +517,7 @@ PyImport_Cleanup(void)
PyDict_Clear(modules);
interp->modules = NULL;
Py_DECREF(modules);
+ Py_CLEAR(interp->modules_reloading);
}
@@ -2400,8 +2420,9 @@ import_submodule(PyObject *mod, char *subname, char *fullname)
PyObject *
PyImport_ReloadModule(PyObject *m)
{
+ PyObject *modules_reloading = PyImport_GetModulesReloading();
PyObject *modules = PyImport_GetModuleDict();
- PyObject *path = NULL, *loader = NULL;
+ PyObject *path = NULL, *loader = NULL, *existing_m = NULL;
char *name, *subname;
char buf[MAXPATHLEN+1];
struct filedescr *fdp;
@@ -2422,20 +2443,30 @@ PyImport_ReloadModule(PyObject *m)
name);
return NULL;
}
+ if ((existing_m = PyDict_GetItemString(modules_reloading, name)) != NULL) {
+ /* Due to a recursive reload, this module is already being reloaded. */
+ Py_INCREF(existing_m);
+ return existing_m;
+ }
+ PyDict_SetItemString(modules_reloading, name, m);
+
subname = strrchr(name, '.');
if (subname == NULL)
subname = name;
else {
PyObject *parentname, *parent;
parentname = PyString_FromStringAndSize(name, (subname-name));
- if (parentname == NULL)
+ if (parentname == NULL) {
+ imp_modules_reloading_clear();
return NULL;
+ }
parent = PyDict_GetItem(modules, parentname);
if (parent == NULL) {
PyErr_Format(PyExc_ImportError,
"reload(): parent %.200s not in sys.modules",
PyString_AS_STRING(parentname));
Py_DECREF(parentname);
+ imp_modules_reloading_clear();
return NULL;
}
Py_DECREF(parentname);
@@ -2450,6 +2481,7 @@ PyImport_ReloadModule(PyObject *m)
if (fdp == NULL) {
Py_XDECREF(loader);
+ imp_modules_reloading_clear();
return NULL;
}
@@ -2466,6 +2498,7 @@ PyImport_ReloadModule(PyObject *m)
*/
PyDict_SetItemString(modules, name, m);
}
+ imp_modules_reloading_clear();
return newm;
}
diff --git a/Python/pystate.c b/Python/pystate.c
index cc25e3e..086789d 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -68,6 +68,7 @@ PyInterpreterState_New(void)
Py_FatalError("Can't initialize threads for interpreter");
#endif
interp->modules = NULL;
+ interp->modules_reloading = NULL;
interp->sysdict = NULL;
interp->builtins = NULL;
interp->tstate_head = NULL;
@@ -107,6 +108,7 @@ PyInterpreterState_Clear(PyInterpreterState *interp)
Py_CLEAR(interp->codec_search_cache);
Py_CLEAR(interp->codec_error_registry);
Py_CLEAR(interp->modules);
+ Py_CLEAR(interp->modules_reloading);
Py_CLEAR(interp->sysdict);
Py_CLEAR(interp->builtins);
}
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 3b5307c..75241fe 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -193,6 +193,9 @@ Py_InitializeEx(int install_sigs)
interp->modules = PyDict_New();
if (interp->modules == NULL)
Py_FatalError("Py_Initialize: can't make modules dictionary");
+ interp->modules_reloading = PyDict_New();
+ if (interp->modules_reloading == NULL)
+ Py_FatalError("Py_Initialize: can't make modules_reloading dictionary");
#ifdef Py_USING_UNICODE
/* Init Unicode implementation; relies on the codec registry */
@@ -530,6 +533,7 @@ Py_NewInterpreter(void)
/* XXX The following is lax in error checking */
interp->modules = PyDict_New();
+ interp->modules_reloading = PyDict_New();
bimod = _PyImport_FindExtension("__builtin__", "__builtin__");
if (bimod != NULL) {