]> granicus.if.org Git - python/commitdiff
Backport of r60190:
authorGregory P. Smith <greg@mad-scientist.com>
Tue, 22 Jan 2008 01:29:11 +0000 (01:29 +0000)
committerGregory P. Smith <greg@mad-scientist.com>
Tue, 22 Jan 2008 01:29:11 +0000 (01:29 +0000)
- Fix Issue #1703448: A joined thread could show up in the
  threading.enumerate() list after the join() for a brief period until
  it actually exited.

Lib/test/test_threading.py
Lib/threading.py
Misc/NEWS

index 8614ecb49c97f75fd9bd9f5736a10cba3ae3e7cd..7c648186f29cf117b7b74813fcdfe2f35631896b 100644 (file)
@@ -3,6 +3,7 @@
 import test.test_support
 from test.test_support import verbose
 import random
+import sys
 import threading
 import thread
 import time
@@ -201,6 +202,24 @@ class ThreadTests(unittest.TestCase):
             t.join()
         # else the thread is still running, and we have no way to kill it
 
+    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.
+        enum = threading.enumerate
+        old_interval = sys.getcheckinterval()
+        sys.setcheckinterval(1)
+        try:
+            for i in xrange(1, 1000):
+                t = threading.Thread(target=lambda: None)
+                t.start()
+                t.join()
+                l = enum()
+                self.assertFalse(t in l,
+                    "#1703448 triggered after %d trials: %s" % (i, l))
+        finally:
+            sys.setcheckinterval(old_interval)
+
+
 def test_main():
     test.test_support.run_unittest(ThreadTests)
 
index 7b0726567020fc064f726456e12384d6974dd07f..bab3b426414c0cc10d54f30235dbaf23893b1ee5 100644 (file)
@@ -524,11 +524,17 @@ class Thread(_Verbose):
                 if __debug__:
                     self._note("%s.__bootstrap(): normal return", self)
         finally:
-            self.__stop()
+            _active_limbo_lock.acquire()
             try:
-                self.__delete()
-            except:
-                pass
+                self.__stop()
+                try:
+                    # We don't call self.__delete() because it also
+                    # grabs _active_limbo_lock.
+                    del _active[_get_ident()]
+                except:
+                    pass
+            finally:
+                _active_limbo_lock.release()
 
     def __stop(self):
         self.__block.acquire()
index dd06f6015786cc1a0dc9f950d8428c60b8f8f8cb..1fa60b0d8033a0641bb64859b02f2160bc7d0472 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -55,6 +55,10 @@ Core and builtins
 
 - Bug #1733488: Fix compilation of bufferobject.c on AIX.
 
+- Fix Issue #1703448: A joined thread could show up in the
+  threading.enumerate() list after the join() for a brief period until
+  it actually exited.
+
 
 Library
 -------