]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Backport 2.217 and 2.218:
authorGuido van Rossum <guido@python.org>
Thu, 13 Feb 2003 17:06:02 +0000 (17:06 +0000)
committerGuido van Rossum <guido@python.org>
Thu, 13 Feb 2003 17:06:02 +0000 (17:06 +0000)
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.

Misc/NEWS
Python/import.c

index dec7862b57f97be965ce51b01729754add62041e..6b1d0094a6651f6becd6713e9c517dfcff0bb470 100644 (file)
--- 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.
index 2c2a3a14afcd76f727b7ba3adb8cc0f926fd3a8f..00ad349a87a724e5707f21484ab9686ada867260 100644 (file)
@@ -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},