summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntoine Pitrou <solipsis@pitrou.net>2009-11-09 16:08:16 (GMT)
committerAntoine Pitrou <solipsis@pitrou.net>2009-11-09 16:08:16 (GMT)
commitb087268217703887c08d580c888813162634353f (patch)
tree31f254e024597a7f45a1f5400fd0404dc7a6fb73
parent3c573af16232928f5623f8fbe0625ecddeaa307a (diff)
downloadcpython-b087268217703887c08d580c888813162634353f.zip
cpython-b087268217703887c08d580c888813162634353f.tar.gz
cpython-b087268217703887c08d580c888813162634353f.tar.bz2
Merged revisions 76172 via svnmerge from
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()`. ........
-rw-r--r--Lib/test/lock_tests.py13
-rw-r--r--Lib/test/test_threading.py6
-rw-r--r--Lib/threading.py18
-rw-r--r--Misc/NEWS4
4 files changed, 29 insertions, 12 deletions
diff --git a/Lib/test/lock_tests.py b/Lib/test/lock_tests.py
index f9c2259..04f7422 100644
--- a/Lib/test/lock_tests.py
+++ b/Lib/test/lock_tests.py
@@ -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):
"""
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
index 5e18243..41f57dc 100644
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -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()
diff --git a/Lib/threading.py b/Lib/threading.py
index d5412e9..4bb0182 100644
--- a/Lib/threading.py
+++ b/Lib/threading.py
@@ -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):
diff --git a/Misc/NEWS b/Misc/NEWS
index 94c16bb..8c0f0ec 100644
--- 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.