summaryrefslogtreecommitdiffstats
path: root/Python
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
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')
-rw-r--r--Python/errors.c2
-rw-r--r--Python/import.c74
-rw-r--r--Python/mactoolboxglue.c2
3 files changed, 53 insertions, 25 deletions
diff --git a/Python/errors.c b/Python/errors.c
index 63acf33..1c29160 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -690,7 +690,7 @@ PyErr_WarnExplicit(PyObject *category, const char *message,
{
PyObject *mod, *dict, *func = NULL;
- mod = PyImport_ImportModule("warnings");
+ mod = PyImport_ImportModuleNoBlock("warnings");
if (mod != NULL) {
dict = PyModule_GetDict(mod);
func = PyDict_GetItemString(dict, "warn_explicit");
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);
diff --git a/Python/mactoolboxglue.c b/Python/mactoolboxglue.c
index 26a1308..8ad0d6d 100644
--- a/Python/mactoolboxglue.c
+++ b/Python/mactoolboxglue.c
@@ -36,7 +36,7 @@ PyMac_StrError(int err)
PyObject *m;
PyObject *rv;
- m = PyImport_ImportModule("MacOS");
+ m = PyImport_ImportModuleNoBlock("MacOS");
if (!m) {
if (Py_VerboseFlag)
PyErr_Print();