From 692323488baf518117d3ede90189812723f39948 Mon Sep 17 00:00:00 2001 From: Tim Peters Date: Thu, 30 Aug 2001 05:16:13 +0000 Subject: [PATCH] Add a new function imp.lock_held(), and use it to skip test_threaded_import when that test is doomed to deadlock. --- Doc/lib/libimp.tex | 13 +++++++++++++ Lib/test/test_threaded_import.py | 10 ++++++---- Misc/NEWS | 9 +++++++++ Python/import.c | 19 +++++++++++++++++++ 4 files changed, 47 insertions(+), 4 deletions(-) diff --git a/Doc/lib/libimp.tex b/Doc/lib/libimp.tex index 23391ffde36..a96839fe7ae 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 1e1c55321f9..e022c5fe924 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 35737acc115..d660df8e31f 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 5c2a9adee4f..52ad85e99e3 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},