diff options
author | Christian Heimes <christian@cheimes.de> | 2008-01-03 22:16:32 (GMT) |
---|---|---|
committer | Christian Heimes <christian@cheimes.de> | 2008-01-03 22:16:32 (GMT) |
commit | 000a074c955a1964959ee908300ef49b41170a06 (patch) | |
tree | af32b732d8b3285969bd524a4af25b6533adbb4c /Python/import.c | |
parent | 0a83d79268e9d2b36decc78845cf71baced4ccc6 (diff) | |
download | cpython-000a074c955a1964959ee908300ef49b41170a06.zip cpython-000a074c955a1964959ee908300ef49b41170a06.tar.gz cpython-000a074c955a1964959ee908300ef49b41170a06.tar.bz2 |
Modified PyImport_Import and PyImport_ImportModule to always use absolute imports by calling __import__ with an explicit level of 0
Added a new API function PyImport_ImportModuleNoBlock. It solves the problem with dead locks when mixing threads and imports
Diffstat (limited to 'Python/import.c')
-rw-r--r-- | Python/import.c | 74 |
1 files changed, 51 insertions, 23 deletions
diff --git a/Python/import.c b/Python/import.c index bcae9b2..e191bd5 100644 --- a/Python/import.c +++ b/Python/import.c @@ -1985,6 +1985,53 @@ PyImport_ImportModule(const char *name) return result; } +/* Import a module without blocking + * + * At first it tries to fetch the module from sys.modules. If the module was + * never loaded before it loads it with PyImport_ImportModule() unless another + * thread holds the import lock. In the latter case the function raises an + * ImportError instead of blocking. + * + * Returns the module object with incremented ref count. + */ +PyObject * +PyImport_ImportModuleNoBlock(const char *name) +{ + PyObject *result; + PyObject *modules; + long me; + + /* Try to get the module from sys.modules[name] */ + modules = PyImport_GetModuleDict(); + if (modules == NULL) + return NULL; + + result = PyDict_GetItemString(modules, name); + if (result != NULL) { + Py_INCREF(result); + return result; + } + else { + PyErr_Clear(); + } + + /* check the import lock + * me might be -1 but I ignore the error here, the lock function + * takes care of the problem */ + me = PyThread_get_thread_ident(); + if (import_lock_thread == -1 || import_lock_thread == me) { + /* no thread or me is holding the lock */ + return PyImport_ImportModule(name); + } + else { + PyErr_Format(PyExc_ImportError, + "Failed to import %.200s because the import lock" + "is held by another thread.", + name); + return NULL; + } +} + /* Forward declarations for helper routines */ static PyObject *get_parent(PyObject *globals, char *buf, Py_ssize_t *p_buflen, int level); @@ -2054,26 +2101,6 @@ import_module_level(char *name, PyObject *globals, PyObject *locals, return tail; } -/* For DLL compatibility */ -#undef PyImport_ImportModuleEx -PyObject * -PyImport_ImportModuleEx(char *name, PyObject *globals, PyObject *locals, - PyObject *fromlist) -{ - PyObject *result; - lock_import(); - result = import_module_level(name, globals, locals, fromlist, -1); - if (unlock_import() < 0) { - Py_XDECREF(result); - PyErr_SetString(PyExc_RuntimeError, - "not holding the import lock"); - return NULL; - } - return result; -} -#define PyImport_ImportModuleEx(n, g, l, f) \ - PyImport_ImportModuleLevel(n, g, l, f, -1); - PyObject * PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, PyObject *fromlist, int level) @@ -2646,9 +2673,10 @@ PyImport_Import(PyObject *module_name) if (import == NULL) goto err; - /* Call the __import__ function with the proper argument list */ - r = PyObject_CallFunctionObjArgs(import, module_name, globals, - globals, silly_list, NULL); + /* Call the __import__ function with the proper argument list + * Always use absolute import here. */ + r = PyObject_CallFunction(import, "OOOOi", module_name, globals, + globals, silly_list, 0, NULL); err: Py_XDECREF(globals); |