New submission from Christian Heimes:
The patch adds a new API method _PyImport_ImportModuleNoLock(const char
*name). It works mostly like PyImport_ImportModule except it does not
block. It tries to fetch the module from sys.modules first and falls
back to PyImport_ImportModule UNLESS the import lock is held by another
thread.
It fixes several issues related to dead locks when a thread uses a
function that imports a module but another thread holds the lock. It
doesn't require static caching of modules.
The patch is against py3k but I can backport it to 2.6.
----------
files: import_nolock.diff
messages: 58272
nosy: gvanrossum, tiran
priority: normal
severity: normal
status: open
title: Patch for new API method _PyImport_ImportModuleNoLock(char *name)
versions: Python 2.6, Python 3.0
Added file: http://bugs.python.org/file8888/import_nolock.diff
__________________________________
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1567>
__________________________________
Index: Python/errors.c
===================================================================
--- Python/errors.c (Revision 59405)
+++ Python/errors.c (Arbeitskopie)
@@ -711,7 +711,7 @@
{
PyObject *mod, *dict, *func = NULL;
- mod = PyImport_ImportModule("warnings");
+ mod = _PyImport_ImportModuleNoLock("warnings");
if (mod != NULL) {
dict = PyModule_GetDict(mod);
func = PyDict_GetItemString(dict, "warn_explicit");
Index: Python/mactoolboxglue.c
===================================================================
--- Python/mactoolboxglue.c (Revision 59405)
+++ Python/mactoolboxglue.c (Arbeitskopie)
@@ -36,7 +36,7 @@
PyObject *m;
PyObject *rv;
- m = PyImport_ImportModule("MacOS");
+ m = _PyImport_ImportModuleNoLock("MacOS");
if (!m) {
if (Py_VerboseFlag)
PyErr_Print();
Index: Python/ast.c
===================================================================
--- Python/ast.c (Revision 59405)
+++ Python/ast.c (Arbeitskopie)
@@ -56,7 +56,7 @@
identifier; if so, normalize to NFKC. */
for (; *u; u++) {
if (*u >= 128) {
- PyObject *m = PyImport_ImportModule("unicodedata");
+ PyObject *m = _PyImport_ImportModuleNoLock("unicodedata");
PyObject *id2;
if (!m)
return NULL;
Index: Python/import.c
===================================================================
--- Python/import.c (Revision 59405)
+++ Python/import.c (Arbeitskopie)
@@ -1895,6 +1895,53 @@
return result;
}
+/* Import a module without blocking
+ *
+ * It tries to fetch the module from sys.modules. If the module was never
+ * loaded before it loads it with PyImport_ImportModule(), When the import
+ * lock is held by another thread it fails with an import error instead of
+ * blocking.
+ *
+ * Returns the module object with incremented ref count.
+ */
+PyObject *
+_PyImport_ImportModuleNoLock(const char *name)
+{
+ PyObject *result;
+ PyObject *modules;
+ long me;
+
+ /* Try to get the module from sys.modules[name] */
+ modules = PySys_GetObject("modules");
+ 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: Python/bltinmodule.c
===================================================================
--- Python/bltinmodule.c (Revision 59405)
+++ Python/bltinmodule.c (Arbeitskopie)
@@ -261,7 +261,7 @@
builtin_filter(PyObject *self, PyObject *args)
{
PyObject *itertools, *ifilter, *result;
- itertools = PyImport_ImportModule("itertools");
+ itertools = _PyImport_ImportModuleNoLock("itertools");
if (itertools == NULL)
return NULL;
ifilter = PyObject_GetAttrString(itertools, "ifilter");
@@ -776,7 +776,7 @@
builtin_map(PyObject *self, PyObject *args)
{
PyObject *itertools, *imap, *result;
- itertools = PyImport_ImportModule("itertools");
+ itertools = _PyImport_ImportModuleNoLock("itertools");
if (itertools == NULL)
return NULL;
imap = PyObject_GetAttrString(itertools, "imap");
Index: Include/py_curses.h
===================================================================
--- Include/py_curses.h (Revision 59405)
+++ Include/py_curses.h (Arbeitskopie)
@@ -90,7 +90,7 @@
#define import_curses() \
{ \
- PyObject *module = PyImport_ImportModule("_curses"); \
+ PyObject *module = _PyImport_ImportModuleNoLock("_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 59405)
+++ 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_ImportModuleNoLock(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 59405)
+++ Objects/unicodeobject.c (Arbeitskopie)
@@ -2800,7 +2800,7 @@
if (ucnhash_CAPI == NULL) {
/* load the unicode data module */
PyObject *m, *api;
- m = PyImport_ImportModule("unicodedata");
+ m = _PyImport_ImportModuleNoLock("unicodedata");
if (m == NULL)
goto ucnhashError;
api = PyObject_GetAttrString(m, "ucnhash_CAPI");
Index: Objects/fileobject.c
===================================================================
--- Objects/fileobject.c (Revision 59405)
+++ Objects/fileobject.c (Arbeitskopie)
@@ -31,7 +31,7 @@
{
PyObject *io, *stream, *nameobj = NULL;
- io = PyImport_ImportModule("io");
+ io = _PyImport_ImportModuleNoLock("io");
if (io == NULL)
return NULL;
stream = PyObject_CallMethod(io, "open", "isisssi", fd, mode,
Index: Parser/tokenizer.c
===================================================================
--- Parser/tokenizer.c (Revision 59405)
+++ Parser/tokenizer.c (Arbeitskopie)
@@ -452,7 +452,7 @@
{
PyObject *readline = NULL, *stream = NULL, *io = NULL;
- io = PyImport_ImportModule("io");
+ io = _PyImport_ImportModuleNoLock("io");
if (io == NULL)
goto cleanup;
Index: Mac/Modules/MacOS.c
===================================================================
--- Mac/Modules/MacOS.c (Revision 59405)
+++ Mac/Modules/MacOS.c (Arbeitskopie)
@@ -356,7 +356,7 @@
PyObject *m, *rv;
errors_loaded = 1;
- m = PyImport_ImportModule("macresource");
+ m = _PyImport_ImportModuleNoLock("macresource");
if (!m) {
if (Py_VerboseFlag)
PyErr_Print();
Index: PC/bdist_wininst/install.c
===================================================================
--- PC/bdist_wininst/install.c (Revision 59405)
+++ PC/bdist_wininst/install.c (Arbeitskopie)
@@ -654,7 +654,7 @@
if (!Py_BuildValue || !PyArg_ParseTuple || !PyErr_Format)
return 1;
- mod = PyImport_ImportModule("builtins");
+ mod = _PyImport_ImportModuleNoLock("builtins");
if (mod) {
int i;
g_PyExc_ValueError = PyObject_GetAttrString(mod, "ValueError");
Index: Modules/_ctypes/callbacks.c
===================================================================
--- Modules/_ctypes/callbacks.c (Revision 59405)
+++ Modules/_ctypes/callbacks.c (Arbeitskopie)
@@ -367,7 +367,7 @@
if (context == NULL)
context = PyUnicode_FromString("_ctypes.DllGetClassObject");
- mod = PyImport_ImportModule("ctypes");
+ mod = _PyImport_ImportModuleNoLock("ctypes");
if (!mod) {
PyErr_WriteUnraisable(context ? context : Py_None);
/* There has been a warning before about this already */
@@ -446,7 +446,7 @@
if (context == NULL)
context = PyUnicode_FromString("_ctypes.DllCanUnloadNow");
- mod = PyImport_ImportModule("ctypes");
+ mod = _PyImport_ImportModuleNoLock("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 59405)
+++ Modules/datetimemodule.c (Arbeitskopie)
@@ -1329,7 +1329,7 @@
goto Done;
{
PyObject *format;
- PyObject *time = PyImport_ImportModule("time");
+ PyObject *time = _PyImport_ImportModuleNoLock("time");
if (time == NULL)
goto Done;
format = PyUnicode_FromString(PyString_AS_STRING(newfmt));
@@ -1357,7 +1357,7 @@
time_time(void)
{
PyObject *result = NULL;
- PyObject *time = PyImport_ImportModule("time");
+ PyObject *time = _PyImport_ImportModuleNoLock("time");
if (time != NULL) {
result = PyObject_CallMethod(time, "time", "()");
@@ -1375,7 +1375,7 @@
PyObject *time;
PyObject *result = NULL;
- time = PyImport_ImportModule("time");
+ time = _PyImport_ImportModuleNoLock("time");
if (time != NULL) {
result = PyObject_CallMethod(time, "struct_time",
"((iiiiiiiii))",
@@ -3821,7 +3821,7 @@
if (!PyArg_ParseTuple(args, "uu:strptime", &string, &format))
return NULL;
- if ((module = PyImport_ImportModule("time")) == NULL)
+ if ((module = _PyImport_ImportModuleNoLock("time")) == NULL)
return NULL;
obj = PyObject_CallMethod(module, "strptime", "uu", string, format);
Py_DECREF(module);
Index: Modules/socketmodule.h
===================================================================
--- Modules/socketmodule.h (Revision 59405)
+++ Modules/socketmodule.h (Arbeitskopie)
@@ -222,7 +222,7 @@
void *api;
DPRINTF("Importing the %s C API...\n", apimodule);
- mod = PyImport_ImportModule(apimodule);
+ mod = _PyImport_ImportModuleNoLock(apimodule);
if (mod == NULL)
goto onError;
DPRINTF(" %s package found\n", apimodule);
Index: Modules/cjkcodecs/cjkcodecs.h
===================================================================
--- Modules/cjkcodecs/cjkcodecs.h (Revision 59405)
+++ Modules/cjkcodecs/cjkcodecs.h (Arbeitskopie)
@@ -245,7 +245,7 @@
static PyObject *cofunc = NULL;
if (cofunc == NULL) {
- PyObject *mod = PyImport_ImportModule("_multibytecodec");
+ PyObject *mod = _PyImport_ImportModuleNoLock("_multibytecodec");
if (mod == NULL)
return NULL;
cofunc = PyObject_GetAttrString(mod, "__create_codec");
Index: Modules/_bsddb.c
===================================================================
--- Modules/_bsddb.c (Revision 59405)
+++ Modules/_bsddb.c (Arbeitskopie)
@@ -6002,7 +6002,7 @@
* using one base class. */
PyDict_SetItemString(d, "KeyError", PyExc_KeyError);
{
- PyObject *builtin_mod = PyImport_ImportModule("builtins");
+ PyObject *builtin_mod = _PyImport_ImportModuleNoLock("builtins");
PyDict_SetItemString(d, "__builtins__", builtin_mod);
}
PyRun_String("class DBNotFoundError(DBError, KeyError): pass\n"
Index: Modules/zipimport.c
===================================================================
--- Modules/zipimport.c (Revision 59405)
+++ Modules/zipimport.c (Arbeitskopie)
@@ -766,7 +766,7 @@
let's avoid a stack overflow. */
return NULL;
importing_zlib = 1;
- zlib = PyImport_ImportModule("zlib"); /* import zlib */
+ zlib = _PyImport_ImportModuleNoLock("zlib");
importing_zlib = 0;
if (zlib != NULL) {
decompress = PyObject_GetAttrString(zlib,
Index: Modules/timemodule.c
===================================================================
--- Modules/timemodule.c (Revision 59405)
+++ Modules/timemodule.c (Arbeitskopie)
@@ -555,7 +555,7 @@
static PyObject *
time_strptime(PyObject *self, PyObject *args)
{
- PyObject *strptime_module = PyImport_ImportModule("_strptime");
+ PyObject *strptime_module = _PyImport_ImportModuleNoLock("_strptime");
PyObject *strptime_result;
if (!strptime_module)
@@ -667,7 +667,7 @@
{
PyObject* m;
- m = PyImport_ImportModule("time");
+ m = _PyImport_ImportModuleNoLock("time");
if (m == NULL) {
return NULL;
}
Index: Modules/gcmodule.c
===================================================================
--- Modules/gcmodule.c (Revision 59405)
+++ Modules/gcmodule.c (Arbeitskopie)
@@ -1210,7 +1210,7 @@
* the import and triggers an assertion.
*/
if (tmod == NULL) {
- tmod = PyImport_ImportModule("time");
+ tmod = _PyImport_ImportModuleNoLock("time");
if (tmod == NULL)
PyErr_Clear();
}
Index: Modules/parsermodule.c
===================================================================
--- Modules/parsermodule.c (Revision 59405)
+++ Modules/parsermodule.c (Arbeitskopie)
@@ -3093,7 +3093,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_ImportModuleNoLock("copy_reg");
if (copyreg != NULL) {
PyObject *func, *pickler;
Index: Modules/posixmodule.c
===================================================================
--- Modules/posixmodule.c (Revision 59405)
+++ Modules/posixmodule.c (Arbeitskopie)
@@ -4217,7 +4217,7 @@
return posix_error();
if (struct_rusage == NULL) {
- PyObject *m = PyImport_ImportModule("resource");
+ PyObject *m = _PyImport_ImportModuleNoLock("resource");
if (m == NULL)
return NULL;
struct_rusage = PyObject_GetAttrString(m, "struct_rusage");
Index: Modules/_cursesmodule.c
===================================================================
--- Modules/_cursesmodule.c (Revision 59405)
+++ Modules/_cursesmodule.c (Arbeitskopie)
@@ -2316,7 +2316,7 @@
update_lines_cols(void)
{
PyObject *o;
- PyObject *m = PyImport_ImportModule("curses");
+ PyObject *m = _PyImport_ImportModuleNoLock("curses");
if (!m)
return 0;
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com