mirror of
https://github.com/python/cpython.git
synced 2025-07-19 17:25:54 +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
|
@ -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…
Add table
Add a link
Reference in a new issue