summaryrefslogtreecommitdiffstats
path: root/Python/import.c
diff options
context:
space:
mode:
authorChristian Heimes <christian@cheimes.de>2008-01-03 22:16:32 (GMT)
committerChristian Heimes <christian@cheimes.de>2008-01-03 22:16:32 (GMT)
commit000a074c955a1964959ee908300ef49b41170a06 (patch)
treeaf32b732d8b3285969bd524a4af25b6533adbb4c /Python/import.c
parent0a83d79268e9d2b36decc78845cf71baced4ccc6 (diff)
downloadcpython-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.c74
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);