]> granicus.if.org Git - python/commitdiff
Merged revisions 76172 via svnmerge from
authorAntoine Pitrou <solipsis@pitrou.net>
Mon, 9 Nov 2009 16:08:16 +0000 (16:08 +0000)
committerAntoine Pitrou <solipsis@pitrou.net>
Mon, 9 Nov 2009 16:08:16 +0000 (16:08 +0000)
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r76172 | antoine.pitrou | 2009-11-09 17:00:11 +0100 (lun., 09 nov. 2009) | 5 lines

  Issue #7282: Fix a memory leak when an RLock was used in a thread other
  than those started through `threading.Thread` (for example, using
  `thread.start_new_thread()`.
........

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

index f9c2259914c2002757c37f93859ab166dd1886a5..04f7422c8de76917d34ce9a7cab9085716e5cd57 100644 (file)
@@ -130,6 +130,19 @@ class BaseLockTests(BaseTestCase):
         # Check the lock is unacquired
         Bunch(f, 1).wait_for_finished()
 
+    def test_thread_leak(self):
+        # The lock shouldn't leak a Thread instance when used from a foreign
+        # (non-threading) thread.
+        lock = self.locktype()
+        def f():
+            lock.acquire()
+            lock.release()
+        n = len(threading.enumerate())
+        # We run many threads in the hope that existing threads ids won't
+        # be recycled.
+        Bunch(f, 15).wait_for_finished()
+        self.assertEqual(n, len(threading.enumerate()))
+
 
 class LockTests(BaseLockTests):
     """
index 5e18243743f420ca69fd37f242a05ad6c977f51e..41f57dc3120ed0e1d35cf326aab4371892475f22 100644 (file)
@@ -143,11 +143,9 @@ class ThreadTests(BaseTestCase):
     def test_foreign_thread(self):
         # Check that a "foreign" thread can use the threading module.
         def f(mutex):
-            # Acquiring an RLock forces an entry for the foreign
+            # Calling current_thread() forces an entry for the foreign
             # thread to get made in the threading._active map.
-            r = threading.RLock()
-            r.acquire()
-            r.release()
+            threading.current_thread()
             mutex.release()
 
         mutex = threading.Lock()
index d5412e935c7b9cea573510c63eef48e29ac26e17..4bb0182e66f14730caa666825b33056c01b27edb 100644 (file)
@@ -92,14 +92,16 @@ class _RLock(_Verbose):
 
     def __repr__(self):
         owner = self._owner
-        return "<%s(%s, %d)>" % (
-                self.__class__.__name__,
-                owner and owner.name,
-                self._count)
+        try:
+            owner = _active[owner].name
+        except KeyError:
+            pass
+        return "<%s owner=%r count=%d>" % (
+                self.__class__.__name__, owner, self._count)
 
     def acquire(self, blocking=True):
-        me = current_thread()
-        if self._owner is me:
+        me = _get_ident()
+        if self._owner == me:
             self._count = self._count + 1
             if __debug__:
                 self._note("%s.acquire(%s): recursive success", self, blocking)
@@ -118,7 +120,7 @@ class _RLock(_Verbose):
     __enter__ = acquire
 
     def release(self):
-        if self._owner is not current_thread():
+        if self._owner != _get_ident():
             raise RuntimeError("cannot release un-acquired lock")
         self._count = count = self._count - 1
         if not count:
@@ -152,7 +154,7 @@ class _RLock(_Verbose):
         return (count, owner)
 
     def _is_owned(self):
-        return self._owner is current_thread()
+        return self._owner == _get_ident()
 
 
 def Condition(*args, **kwargs):
index 94c16bb900b05cc7917552273aea4919bd5c02c5..8c0f0ecbd1f3377134ec526a02aab8c4cf1b16ea 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -123,6 +123,10 @@ C-API
 Library
 -------
 
+- Issue #7282: Fix a memory leak when an RLock was used in a thread other
+  than those started through `threading.Thread` (for example, using
+  `_thread.start_new_thread()`).
+
 - Issue #7187: Importlib would not silence the IOError raised when trying to
   write new bytecode when it was made read-only.