From: Guido van Rossum Date: Thu, 13 Feb 2003 17:06:02 +0000 (+0000) Subject: Backport 2.217 and 2.218: X-Git-Tag: v2.2.3c1~139 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=466a3a7150b6cec85f3b9584adfb0e1da2227b26;p=thirdparty%2FPython%2Fcpython.git Backport 2.217 and 2.218: Provide access to the import lock, fixing SF bug #580952. This is mostly from SF patch #683257, but I had to change unlock_import() to return an error value to avoid fatal error. --- diff --git a/Misc/NEWS b/Misc/NEWS index dec7862b57f9..6b1d0094a665 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -2,6 +2,12 @@ What's New in Python 2.2.3 ? Release date: XX-XXX-2003 ============================ +- The imp module now has ways to acquire and release the "import + lock": imp.acquire_lock() and imp.release_lock(). Note: this is a + reentrant lock, so releasing the lock only truly releases it when + this is the last release_lock() call. You can check with + imp.lock_held(). (SF bug #580952 and patch #683257.) + - Through a bytecode optimizer bug (and I bet you didn't even know Python *had* a bytecode optimizer :-), "unsigned" hex/oct constants with a leading minus sign would come out with the wrong sign. diff --git a/Python/import.c b/Python/import.c index 2c2a3a14afcd..00ad349a87a7 100644 --- a/Python/import.c +++ b/Python/import.c @@ -161,7 +161,8 @@ lock_import(void) import_lock_level++; return; } - if (import_lock_thread != -1 || !PyThread_acquire_lock(import_lock, 0)) { + if (import_lock_thread != -1 || !PyThread_acquire_lock(import_lock, 0)) + { PyThreadState *tstate = PyEval_SaveThread(); PyThread_acquire_lock(import_lock, 1); PyEval_RestoreThread(tstate); @@ -170,25 +171,26 @@ lock_import(void) import_lock_level = 1; } -static void +static int unlock_import(void) { long me = PyThread_get_thread_ident(); if (me == -1) - return; /* Too bad */ + return 0; /* Too bad */ if (import_lock_thread != me) - Py_FatalError("unlock_import: not holding the import lock"); + return -1; import_lock_level--; if (import_lock_level == 0) { import_lock_thread = -1; PyThread_release_lock(import_lock); } + return 1; } #else #define lock_import() -#define unlock_import() +#define unlock_import() 0 #endif @@ -204,6 +206,34 @@ imp_lock_held(PyObject *self, PyObject *args) #endif } +static PyObject * +imp_acquire_lock(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, ":acquire_lock")) + return NULL; +#ifdef WITH_THREAD + lock_import(); +#endif + Py_INCREF(Py_None); + return Py_None; +} + +static PyObject * +imp_release_lock(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, ":release_lock")) + return NULL; +#ifdef WITH_THREAD + if (unlock_import() < 0) { + PyErr_SetString(PyExc_RuntimeError, + "not holding the import lock"); + return NULL; + } +#endif + Py_INCREF(Py_None); + return Py_None; +} + /* Helper for sys */ PyObject * @@ -1656,7 +1686,12 @@ PyImport_ImportModuleEx(char *name, PyObject *globals, PyObject *locals, PyObject *result; lock_import(); result = import_module_ex(name, globals, locals, fromlist); - unlock_import(); + if (unlock_import() < 0) { + Py_XDECREF(result); + PyErr_SetString(PyExc_RuntimeError, + "not holding the import lock"); + return NULL; + } return result; } @@ -2426,6 +2461,18 @@ Return 1 if the import lock is currently held.\n\ On platforms without threads, return 0.\ "; +static char doc_acquire_lock[] = "\ +acquire_lock() -> None\n\ +Acquires the interpreter's import lock for the current thread.\n\ +This lock should be used by import hooks to ensure thread-safety\n\ +when importing modules.\n\ +On platforms without threads, this function does nothing."; + +static char doc_release_lock[] = "\ +release_lock() -> None\n\ +Release the interpreter's import lock.\n\ +On platforms without threads, this function does nothing."; + static PyMethodDef imp_methods[] = { {"find_module", imp_find_module, 1, doc_find_module}, {"get_magic", imp_get_magic, 1, doc_get_magic}, @@ -2433,6 +2480,8 @@ static PyMethodDef imp_methods[] = { {"load_module", imp_load_module, 1, doc_load_module}, {"new_module", imp_new_module, 1, doc_new_module}, {"lock_held", imp_lock_held, 1, doc_lock_held}, + {"acquire_lock", imp_acquire_lock, 1, doc_acquire_lock}, + {"release_lock", imp_release_lock, 1, doc_release_lock}, /* The rest are obsolete */ {"get_frozen_object", imp_get_frozen_object, 1}, {"init_builtin", imp_init_builtin, 1},