[Python-Dev] test_threaded_import
Tim Peters
tim.one@home.com
Wed, 29 Aug 2001 19:42:59 -0400
[Jack Jansen]
> ...
> Elementary, my dear Watson. I do a "make install", which runs the
> regression tests twice, succeeding both times. Then I do "python" and
> "import autotest", at which point it fails, thereby failing
> approximately 30% of the time. Of course, not being Sherlock Jansen, I
> didn't realise autotest!=regrtest for this:-)
Ah, a signficant digits error. Had you said "approximately 33% of the
time", or even "approximately 3e1%", I would have guessed instantly <wink>.
> ...
> I'll apply your patch, which seems to fix the problem fine for the
> time being. Still, there's three issues that I think need to be solved
> at some point:
> - the fact that you (or some other thread) are holding the import lock
> is one of the few Python state bits that are not open to
> introspection.
The patch below adds introspection, sufficient to avoid special-casing
autotest. Guido? I'd upload the patch to SF instead, but, as you've (Jack)
noted, that's a black hole <0.9 wink>.
> - There may be denial of service attacks possible with this if a 16
> year old scriptkiddy can think of a way to exploit it in a
> restricted interpreter.
Someone else will have to worry about that; in a world where a 20-character
regexp can take centuries to match, I don't take DOS from a general-purpose
programming language seriously.
> - The whole idea that a process deadlocked on semaphore locks is
> completely uninterruptible also smells bad.
That's threads for you: start a thread, risk a deadlock. There's no
portable way to interrupt a thread waiting on a lock, and, e.g., no *safe*
way at all on Windows short of killing the whole process.
Index: Python/import.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/import.c,v
retrieving revision 2.185
diff -c -r2.185 import.c
*** Python/import.c 2001/08/13 23:05:44 2.185
--- Python/import.c 2001/08/29 23:25:28
***************
*** 138,143 ****
--- 138,151 ----
static long import_lock_thread = -1;
static int import_lock_level = 0;
+ static PyObject *
+ imp_lock_held(PyObject *self, PyObject *args)
+ {
+ if (!PyArg_ParseTuple(args, ":lock_held"))
+ return NULL;
+ return PyInt_FromLong(import_lock_thread != -1);
+ }
+
static void
lock_import(void)
{
***************
*** 179,184 ****
--- 187,200 ----
#define lock_import()
#define unlock_import()
+ static PyObject *
+ imp_lock_held(PyObject *self, PyObject *args)
+ {
+ if (!PyArg_ParseTuple(args, ":lock_held"))
+ return NULL;
+ return PyInt_FromLong(0);
+ }
+
#endif
/* Helper for sys */
***************
*** 2339,2350 ****
--- 2355,2373 ----
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},