mirror of
https://github.com/python/cpython.git
synced 2025-07-24 03:35:53 +00:00
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
2 changed files with 59 additions and 7 deletions
|
@ -10,7 +10,7 @@ What's New in Python 2.3 alpha 2?
|
||||||
*Release date: XX-XXX-2003*
|
*Release date: XX-XXX-2003*
|
||||||
|
|
||||||
Core and builtins
|
Core and builtins
|
||||||
----------------
|
-----------------
|
||||||
|
|
||||||
- Through a bytecode optimizer bug (and I bet you didn't even know
|
- Through a bytecode optimizer bug (and I bet you didn't even know
|
||||||
Python *had* a bytecode optimizer :-), "unsigned" hex/oct constants
|
Python *had* a bytecode optimizer :-), "unsigned" hex/oct constants
|
||||||
|
@ -75,6 +75,12 @@ Core and builtins
|
||||||
Extension modules
|
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.
|
- Fix some bugs in the parser module. SF bug #678518.
|
||||||
|
|
||||||
- Thanks to Scott David Daniels, a subtle bug in how the zlib
|
- Thanks to Scott David Daniels, a subtle bug in how the zlib
|
||||||
|
|
|
@ -252,7 +252,8 @@ lock_import(void)
|
||||||
import_lock_level++;
|
import_lock_level++;
|
||||||
return;
|
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();
|
PyThreadState *tstate = PyEval_SaveThread();
|
||||||
PyThread_acquire_lock(import_lock, 1);
|
PyThread_acquire_lock(import_lock, 1);
|
||||||
PyEval_RestoreThread(tstate);
|
PyEval_RestoreThread(tstate);
|
||||||
|
@ -261,25 +262,26 @@ lock_import(void)
|
||||||
import_lock_level = 1;
|
import_lock_level = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static int
|
||||||
unlock_import(void)
|
unlock_import(void)
|
||||||
{
|
{
|
||||||
long me = PyThread_get_thread_ident();
|
long me = PyThread_get_thread_ident();
|
||||||
if (me == -1)
|
if (me == -1)
|
||||||
return; /* Too bad */
|
return 0; /* Too bad */
|
||||||
if (import_lock_thread != me)
|
if (import_lock_thread != me)
|
||||||
Py_FatalError("unlock_import: not holding the import lock");
|
return -1;
|
||||||
import_lock_level--;
|
import_lock_level--;
|
||||||
if (import_lock_level == 0) {
|
if (import_lock_level == 0) {
|
||||||
import_lock_thread = -1;
|
import_lock_thread = -1;
|
||||||
PyThread_release_lock(import_lock);
|
PyThread_release_lock(import_lock);
|
||||||
}
|
}
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define lock_import()
|
#define lock_import()
|
||||||
#define unlock_import()
|
#define unlock_import() 0
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -295,6 +297,32 @@ imp_lock_held(PyObject *self, PyObject *args)
|
||||||
#endif
|
#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 */
|
/* Helper for sys */
|
||||||
|
|
||||||
PyObject *
|
PyObject *
|
||||||
|
@ -1970,7 +1998,12 @@ PyImport_ImportModuleEx(char *name, PyObject *globals, PyObject *locals,
|
||||||
PyObject *result;
|
PyObject *result;
|
||||||
lock_import();
|
lock_import();
|
||||||
result = import_module_ex(name, globals, locals, fromlist);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2743,6 +2776,17 @@ PyDoc_STRVAR(doc_lock_held,
|
||||||
Return 1 if the import lock is currently held.\n\
|
Return 1 if the import lock is currently held.\n\
|
||||||
On platforms without threads, return 0.");
|
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[] = {
|
static PyMethodDef imp_methods[] = {
|
||||||
{"find_module", imp_find_module, METH_VARARGS, doc_find_module},
|
{"find_module", imp_find_module, METH_VARARGS, doc_find_module},
|
||||||
{"get_magic", imp_get_magic, METH_VARARGS, doc_get_magic},
|
{"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},
|
{"load_module", imp_load_module, METH_VARARGS, doc_load_module},
|
||||||
{"new_module", imp_new_module, METH_VARARGS, doc_new_module},
|
{"new_module", imp_new_module, METH_VARARGS, doc_new_module},
|
||||||
{"lock_held", imp_lock_held, METH_VARARGS, doc_lock_held},
|
{"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 */
|
/* The rest are obsolete */
|
||||||
{"get_frozen_object", imp_get_frozen_object, METH_VARARGS},
|
{"get_frozen_object", imp_get_frozen_object, METH_VARARGS},
|
||||||
{"init_builtin", imp_init_builtin, METH_VARARGS},
|
{"init_builtin", imp_init_builtin, METH_VARARGS},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue