SF bug #1473760 TempFile can hang on Windows.

Python 2.4 changed ntpath.abspath to do an import
inside the function.  As a result, due to Python's
import lock, anything calling abspath on Windows
(directly, or indirectly like tempfile.TemporaryFile)
hung when it was called from a thread spawned as a
side effect of importing a module.

This is a depressingly frequent problem, and
deserves a more general fix.  I'm settling for
a micro-fix here because this specific one accounts
for a report of Zope Corp's ZEO hanging on Windows,
and it was an odd way to change abspath to begin
with (ntpath needs a different implementation
depending on whether we're actually running on
Windows, and the _obvious_ way to arrange for that
is not to bury a possibly-failing import _inside_
the function).

Note that if/when other micro-fixes of this kind
get made, the new Lib/test/threaded_import_hangers.py
is a convenient place to add tests for them.
This commit is contained in:
Tim Peters 2006-04-21 21:18:10 +00:00
parent 9f7e58afa7
commit 21fbd57d66
4 changed files with 86 additions and 21 deletions

View file

@ -6,7 +6,7 @@
# randrange, and then Python hangs.
import thread
from test.test_support import verbose, TestSkipped
from test.test_support import verbose, TestSkipped, TestFailed
critical_section = thread.allocate_lock()
done = thread.allocate_lock()
@ -25,6 +25,23 @@ def task():
if finished:
done.release()
def test_import_hangers():
import sys
if verbose:
print "testing import hangers ...",
from test import threaded_import_hangers
try:
if threaded_import_hangers.errors:
raise TestFailed(threaded_import_hangers.errors)
elif verbose:
print "OK."
finally:
# In case this test is run again, make sure the helper module
# gets loaded from scratch again.
del sys.modules['test.threaded_import_hangers']
# Tricky: When regrtest imports this module, the thread running regrtest
# grabs the import lock and won't let go of it until this module returns.
# All other threads attempting an import hang for the duration. Since
@ -53,5 +70,7 @@ def test_main(): # magic name! see above
print "OK."
done.release()
test_import_hangers()
if __name__ == "__main__":
test_main()