diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 195c4e8f733..30aa9d57867 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -238,6 +238,35 @@ class ThreadTests(unittest.TestCase): """]) self.assertEqual(rc, 42) + def test_finalize_with_trace(self): + # Issue1733757 + # Avoid a deadlock when sys.settrace steps into threading._shutdown + import subprocess + rc = subprocess.call([sys.executable, "-c", """if 1: + import sys, threading + + # A deadlock-killer, to prevent the + # testsuite to hang forever + def killer(): + import os, time + time.sleep(2) + print 'program blocked; aborting' + os._exit(2) + t = threading.Thread(target=killer) + t.setDaemon(True) + t.start() + + # This is the trace function + def func(frame, event, arg): + threading.currentThread() + return func + + sys.settrace(func) + """]) + self.failIf(rc == 2, "interpreted was blocked") + self.failUnless(rc == 0, "Unexpected error") + + def test_enumerate_after_join(self): # Try hard to trigger #1703448: a thread is still returned in # threading.enumerate() after it has been join()ed. diff --git a/Lib/threading.py b/Lib/threading.py index 516e22ded7d..d497a46dc7b 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -583,15 +583,16 @@ class Thread(_Verbose): # since it isn't if dummy_threading is *not* being used then don't # hide the exception. - _active_limbo_lock.acquire() try: - try: + with _active_limbo_lock: del _active[_get_ident()] - except KeyError: - if 'dummy_threading' not in _sys.modules: - raise - finally: - _active_limbo_lock.release() + # There must not be any python code between the previous line + # and after the lock is released. Otherwise a tracing function + # could try to acquire the lock again in the same thread, (in + # currentThread()), and would block. + except KeyError: + if 'dummy_threading' not in _sys.modules: + raise def join(self, timeout=None): if not self.__initialized: diff --git a/Misc/NEWS b/Misc/NEWS index e9e736c0315..945afdf25da 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -12,6 +12,10 @@ What's New in Python 2.6 alpha 2? Core and builtins ----------------- +- Issue #1733757: The interpreter would hang on shutdown if the tracing + function set by sys.settrace is still active and happens to call + threading.currentThread(). + - Patch #1442: properly report exceptions when the PYTHONSTARTUP file cannot be executed.