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.
This commit is contained in:
parent
47710656e5
commit
c4f4ca91e1
|
@ -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
|
||||
|
|
|
@ -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},
|
||||
|
|
Loading…
Reference in New Issue