summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2003-02-12 21:46:11 (GMT)
committerGuido van Rossum <guido@python.org>2003-02-12 21:46:11 (GMT)
commitc4f4ca91e112a55b2fac5853718a5f05797f30b5 (patch)
treeb7e75170ce51536cf76bbfd58f1901946a7cab50
parent47710656e53717b8369b72efcc486287f61bd69e (diff)
downloadcpython-c4f4ca91e112a55b2fac5853718a5f05797f30b5.zip
cpython-c4f4ca91e112a55b2fac5853718a5f05797f30b5.tar.gz
cpython-c4f4ca91e112a55b2fac5853718a5f05797f30b5.tar.bz2
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. Should this be backported? The patch requested this, but it's a new feature.
-rw-r--r--Misc/NEWS8
-rw-r--r--Python/import.c58
2 files changed, 59 insertions, 7 deletions
diff --git a/Misc/NEWS b/Misc/NEWS
index f1b3a8b..cfcb7ac 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -10,7 +10,7 @@ What's New in Python 2.3 alpha 2?
*Release date: XX-XXX-2003*
Core and builtins
-----------------
+-----------------
- Through a bytecode optimizer bug (and I bet you didn't even know
Python *had* a bytecode optimizer :-), "unsigned" hex/oct constants
@@ -75,6 +75,12 @@ Core and builtins
Extension modules
-----------------
+- 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.)
+
- Fix some bugs in the parser module. SF bug #678518.
- Thanks to Scott David Daniels, a subtle bug in how the zlib
diff --git a/Python/import.c b/Python/import.c
index b2cefc0..f1d3d0c 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -252,7 +252,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);
@@ -261,25 +262,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
@@ -295,6 +297,32 @@ 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
+ 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
+ return Py_None;
+}
+
/* Helper for sys */
PyObject *
@@ -1970,7 +1998,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;
}
@@ -2743,6 +2776,17 @@ PyDoc_STRVAR(doc_lock_held,
Return 1 if the import lock is currently held.\n\
On platforms without threads, return 0.");
+PyDoc_STRVAR(doc_acquire_lock,
+"acquire_lock() -> None\n\
+Acquires the interpreter's import lock for the current thread. This lock
+should be used by import hooks to ensure thread-safety when importing modules.
+On platforms without threads, this function does nothing.");
+
+PyDoc_STRVAR(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, METH_VARARGS, doc_find_module},
{"get_magic", imp_get_magic, METH_VARARGS, doc_get_magic},
@@ -2750,6 +2794,8 @@ static PyMethodDef imp_methods[] = {
{"load_module", imp_load_module, METH_VARARGS, doc_load_module},
{"new_module", imp_new_module, METH_VARARGS, doc_new_module},
{"lock_held", imp_lock_held, METH_VARARGS, doc_lock_held},
+ {"acquire_lock", imp_acquire_lock, METH_VARARGS, doc_acquire_lock},
+ {"release_lock", imp_release_lock, METH_VARARGS, doc_release_lock},
/* The rest are obsolete */
{"get_frozen_object", imp_get_frozen_object, METH_VARARGS},
{"init_builtin", imp_init_builtin, METH_VARARGS},