Index: Python/errors.c =================================================================== --- Python/errors.c (Revision 59672) +++ Python/errors.c (Arbeitskopie) @@ -690,7 +690,7 @@ { 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"); Index: Python/mactoolboxglue.c =================================================================== --- Python/mactoolboxglue.c (Revision 59672) +++ Python/mactoolboxglue.c (Arbeitskopie) @@ -36,7 +36,7 @@ PyObject *m; PyObject *rv; - m = PyImport_ImportModule("MacOS"); + m = PyImport_ImportModuleNoBlock("MacOS"); if (!m) { if (Py_VerboseFlag) PyErr_Print(); Index: Python/import.c =================================================================== --- Python/import.c (Revision 59672) +++ Python/import.c (Arbeitskopie) @@ -1985,6 +1985,53 @@ 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); Index: Include/py_curses.h =================================================================== --- Include/py_curses.h (Revision 59672) +++ Include/py_curses.h (Arbeitskopie) @@ -90,7 +90,7 @@ #define import_curses() \ { \ - PyObject *module = PyImport_ImportModule("_curses"); \ + PyObject *module = PyImport_ImportModuleNoBlock("_curses"); \ if (module != NULL) { \ PyObject *module_dict = PyModule_GetDict(module); \ PyObject *c_api_object = PyDict_GetItemString(module_dict, "_C_API"); \ Index: Include/import.h =================================================================== --- Include/import.h (Revision 59672) +++ Include/import.h (Arbeitskopie) @@ -14,6 +14,7 @@ PyAPI_FUNC(PyObject *) PyImport_GetModuleDict(void); PyAPI_FUNC(PyObject *) PyImport_AddModule(const char *name); PyAPI_FUNC(PyObject *) PyImport_ImportModule(const char *name); +PyAPI_FUNC(PyObject *) PyImport_ImportModuleNoBlock(const char *); PyAPI_FUNC(PyObject *) PyImport_ImportModuleLevel(char *name, PyObject *globals, PyObject *locals, PyObject *fromlist, int level); Index: Objects/unicodeobject.c =================================================================== --- Objects/unicodeobject.c (Revision 59672) +++ Objects/unicodeobject.c (Arbeitskopie) @@ -2216,7 +2216,7 @@ if (ucnhash_CAPI == NULL) { /* load the unicode data module */ PyObject *m, *api; - m = PyImport_ImportModule("unicodedata"); + m = PyImport_ImportModuleNoBlock("unicodedata"); if (m == NULL) goto ucnhashError; api = PyObject_GetAttrString(m, "ucnhash_CAPI"); Index: Mac/Modules/MacOS.c =================================================================== --- Mac/Modules/MacOS.c (Revision 59672) +++ Mac/Modules/MacOS.c (Arbeitskopie) @@ -357,7 +357,7 @@ PyObject *m, *rv; errors_loaded = 1; - m = PyImport_ImportModule("macresource"); + m = PyImport_ImportModuleNoBlock("macresource"); if (!m) { if (Py_VerboseFlag) PyErr_Print(); Index: Doc/c-api/utilities.rst =================================================================== --- Doc/c-api/utilities.rst (Revision 59672) +++ Doc/c-api/utilities.rst (Arbeitskopie) @@ -201,6 +201,22 @@ .. index:: single: modules (in module sys) +.. cfunction:: PyObject* PyImport_ImportModuleNoBlock(const char *name) + + .. index:: + single: `cfunc:PyImport_ImportModule` + + This version of `cfunc:PyImport_ImportModule` does not block. It's intended + to be used in C function which import other modules to execute a function. + The import may block if another thread holds the import lock. The function + `cfunc:PyImport_ImportModuleNoBlock` doesn't block. It first tries to fetch + the module from sys.modules and falls back to `cfunc:PyImport_ImportModule` + unless the the lock is hold. In the latter case the function raises an + ImportError. + + .. versionadded:: 2.6 + + .. cfunction:: PyObject* PyImport_ImportModuleEx(char *name, PyObject *globals, PyObject *locals, PyObject *fromlist) .. index:: builtin: __import__ Index: Modules/_ctypes/callbacks.c =================================================================== --- Modules/_ctypes/callbacks.c (Revision 59672) +++ Modules/_ctypes/callbacks.c (Arbeitskopie) @@ -370,7 +370,7 @@ if (context == NULL) context = PyString_FromString("_ctypes.DllGetClassObject"); - mod = PyImport_ImportModule("ctypes"); + mod = PyImport_ImportModuleNoBlock("ctypes"); if (!mod) { PyErr_WriteUnraisable(context ? context : Py_None); /* There has been a warning before about this already */ @@ -449,7 +449,7 @@ if (context == NULL) context = PyString_FromString("_ctypes.DllCanUnloadNow"); - mod = PyImport_ImportModule("ctypes"); + mod = PyImport_ImportModuleNoBlock("ctypes"); if (!mod) { /* OutputDebugString("Could not import ctypes"); */ /* We assume that this error can only occur when shutting Index: Modules/datetimemodule.c =================================================================== --- Modules/datetimemodule.c (Revision 59672) +++ Modules/datetimemodule.c (Arbeitskopie) @@ -1305,7 +1305,7 @@ if (_PyString_Resize(&newfmt, usednew) < 0) goto Done; { - PyObject *time = PyImport_ImportModule("time"); + PyObject *time = PyImport_ImportModuleNoBlock("time"); if (time == NULL) goto Done; result = PyObject_CallMethod(time, "strftime", "OO", @@ -1353,7 +1353,7 @@ time_time(void) { PyObject *result = NULL; - PyObject *time = PyImport_ImportModule("time"); + PyObject *time = PyImport_ImportModuleNoBlock("time"); if (time != NULL) { result = PyObject_CallMethod(time, "time", "()"); @@ -1371,7 +1371,7 @@ PyObject *time; PyObject *result = NULL; - time = PyImport_ImportModule("time"); + time = PyImport_ImportModuleNoBlock("time"); if (time != NULL) { result = PyObject_CallMethod(time, "struct_time", "((iiiiiiiii))", @@ -3827,7 +3827,7 @@ if (!PyArg_ParseTuple(args, "ss:strptime", &string, &format)) return NULL; - if ((module = PyImport_ImportModule("time")) == NULL) + if ((module = PyImport_ImportModuleNoBlock("time")) == NULL) return NULL; obj = PyObject_CallMethod(module, "strptime", "ss", string, format); Py_DECREF(module); Index: Modules/socketmodule.h =================================================================== --- Modules/socketmodule.h (Revision 59672) +++ Modules/socketmodule.h (Arbeitskopie) @@ -222,7 +222,7 @@ void *api; DPRINTF("Importing the %s C API...\n", apimodule); - mod = PyImport_ImportModule(apimodule); + mod = PyImport_ImportModuleNoBlock(apimodule); if (mod == NULL) goto onError; DPRINTF(" %s package found\n", apimodule); Index: Modules/cjkcodecs/cjkcodecs.h =================================================================== --- Modules/cjkcodecs/cjkcodecs.h (Revision 59672) +++ Modules/cjkcodecs/cjkcodecs.h (Arbeitskopie) @@ -245,7 +245,7 @@ static PyObject *cofunc = NULL; if (cofunc == NULL) { - PyObject *mod = PyImport_ImportModule("_multibytecodec"); + PyObject *mod = PyImport_ImportModuleNoBlock("_multibytecodec"); if (mod == NULL) return NULL; cofunc = PyObject_GetAttrString(mod, "__create_codec"); Index: Modules/zipimport.c =================================================================== --- Modules/zipimport.c (Revision 59672) +++ Modules/zipimport.c (Arbeitskopie) @@ -776,7 +776,7 @@ let's avoid a stack overflow. */ return NULL; importing_zlib = 1; - zlib = PyImport_ImportModule("zlib"); /* import zlib */ + zlib = PyImport_ImportModuleNoBlock("zlib"); importing_zlib = 0; if (zlib != NULL) { decompress = PyObject_GetAttrString(zlib, Index: Modules/timemodule.c =================================================================== --- Modules/timemodule.c (Revision 59672) +++ Modules/timemodule.c (Arbeitskopie) @@ -515,7 +515,7 @@ static PyObject * time_strptime(PyObject *self, PyObject *args) { - PyObject *strptime_module = PyImport_ImportModule("_strptime"); + PyObject *strptime_module = PyImport_ImportModuleNoBlock("_strptime"); PyObject *strptime_result; if (!strptime_module) @@ -627,7 +627,7 @@ { PyObject* m; - m = PyImport_ImportModule("time"); + m = PyImport_ImportModuleNoBlock("time"); if (m == NULL) { return NULL; } Index: Modules/gcmodule.c =================================================================== --- Modules/gcmodule.c (Revision 59672) +++ Modules/gcmodule.c (Arbeitskopie) @@ -1236,7 +1236,7 @@ * the import and triggers an assertion. */ if (tmod == NULL) { - tmod = PyImport_ImportModule("time"); + tmod = PyImport_ImportModuleNoBlock("time"); if (tmod == NULL) PyErr_Clear(); } Index: Modules/parsermodule.c =================================================================== --- Modules/parsermodule.c (Revision 59672) +++ Modules/parsermodule.c (Arbeitskopie) @@ -3269,7 +3269,7 @@ * If this fails, the import of this module will fail because an * exception will be raised here; should we clear the exception? */ - copyreg = PyImport_ImportModule("copy_reg"); + copyreg = PyImport_ImportModuleNoBlock("copy_reg"); if (copyreg != NULL) { PyObject *func, *pickler; Index: Modules/posixmodule.c =================================================================== --- Modules/posixmodule.c (Revision 59672) +++ Modules/posixmodule.c (Arbeitskopie) @@ -5651,7 +5651,7 @@ return posix_error(); if (struct_rusage == NULL) { - PyObject *m = PyImport_ImportModule("resource"); + PyObject *m = PyImport_ImportModuleNoBlock("resource"); if (m == NULL) return NULL; struct_rusage = PyObject_GetAttrString(m, "struct_rusage"); Index: Modules/_cursesmodule.c =================================================================== --- Modules/_cursesmodule.c (Revision 59672) +++ Modules/_cursesmodule.c (Arbeitskopie) @@ -2255,7 +2255,7 @@ update_lines_cols(void) { PyObject *o; - PyObject *m = PyImport_ImportModule("curses"); + PyObject *m = PyImport_ImportModuleNoBlock("curses"); if (!m) return 0;