summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/lib/libimp.tex13
-rw-r--r--Lib/test/test_threaded_import.py10
-rw-r--r--Misc/NEWS9
-rw-r--r--Python/import.c19
4 files changed, 47 insertions, 4 deletions
diff --git a/Doc/lib/libimp.tex b/Doc/lib/libimp.tex
index 23391ff..a96839f 100644
--- a/Doc/lib/libimp.tex
+++ b/Doc/lib/libimp.tex
@@ -93,6 +93,19 @@ Return a new empty module object called \var{name}. This object is
\emph{not} inserted in \code{sys.modules}.
\end{funcdesc}
+\begin{funcdesc}{lock_held}{}
+Return 1 if the import lock is currently held, else 0.
+On platforms without threads, always return 0.
+
+On platforms with threads, a thread executing an import holds an internal
+lock until the import is complete.
+This lock blocks other threads from doing an import until the original
+import completes, which in turn prevents other threads from seeing
+incomplete module objects constructed by the original thread while in
+the process of completing its import (and the imports, if any,
+triggered by that).
+\end{funcdesc}
+
The following constants with integer values, defined in this module,
are used to indicate the search result of \function{find_module()}.
diff --git a/Lib/test/test_threaded_import.py b/Lib/test/test_threaded_import.py
index 1e1c553..e022c5f 100644
--- a/Lib/test/test_threaded_import.py
+++ b/Lib/test/test_threaded_import.py
@@ -32,10 +32,12 @@ def task():
def test_main(): # magic name! see above
global N, done
- import sys
- for modname in sys.modules:
- if modname.find('autotest') >= 0:
- raise TestSkipped("can't run from autotest")
+
+ import imp
+ if imp.lock_held():
+ # This triggers on, e.g., from test import autotest.
+ raise TestSkipped("can't run when import lock is held")
+
done.acquire()
for N in (20, 50) * 3:
if verbose:
diff --git a/Misc/NEWS b/Misc/NEWS
index 35737ac..d660df8 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -8,6 +8,9 @@ Core
Library
++ A new function, imp.lock_held(), returns 1 when the import lock is
+ currently held. See the docs for the imp module.
+
+ pickle, cPickle and marshal on 32-bit platforms can now correctly read
dumps containing ints written on platforms where Python ints are 8 bytes.
When read on a box where Python ints are 4 bytes, such values are
@@ -17,6 +20,12 @@ Tools
Build
+API
+
++ XXX Say something about Neil's GC rework, and that extensions that
+ don't upgrade to the new scheme will still compile but not actually
+ participate in GC.
+
New platforms
Tests
diff --git a/Python/import.c b/Python/import.c
index 5c2a9ad..52ad85e 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -181,6 +181,18 @@ unlock_import(void)
#endif
+static PyObject *
+imp_lock_held(PyObject *self, PyObject *args)
+{
+ if (!PyArg_ParseTuple(args, ":lock_held"))
+ return NULL;
+#ifdef WITH_THREAD
+ return PyInt_FromLong(import_lock_thread != -1);
+#else
+ return PyInt_FromLong(0);
+#endif
+}
+
/* Helper for sys */
PyObject *
@@ -2339,12 +2351,19 @@ Create a new module. Do not enter it in sys.modules.\n\
The module name must include the full package name, if any.\
";
+static char doc_lock_held[] = "\
+lock_held() -> 0 or 1\n\
+Return 1 if the import lock is currently held.\n\
+On platforms without threads, return 0.\
+";
+
static PyMethodDef imp_methods[] = {
{"find_module", imp_find_module, 1, doc_find_module},
{"get_magic", imp_get_magic, 1, doc_get_magic},
{"get_suffixes", imp_get_suffixes, 1, doc_get_suffixes},
{"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},
/* The rest are obsolete */
{"get_frozen_object", imp_get_frozen_object, 1},
{"init_builtin", imp_init_builtin, 1},