Bug #742342: make Python stop segfaulting on infinitely-recursive reload()s. Fixed by patch #922167.
Backported from r54291.
This commit is contained in:
parent
1817f096f4
commit
e19d7a3c0a
|
@ -21,6 +21,7 @@ typedef struct _is {
|
|||
PyObject *modules;
|
||||
PyObject *sysdict;
|
||||
PyObject *builtins;
|
||||
PyObject *modules_reloading;
|
||||
|
||||
PyObject *codec_search_path;
|
||||
PyObject *codec_search_cache;
|
||||
|
|
|
@ -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)
|
|
@ -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()
|
||||
|
|
|
@ -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().
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue