[Python-checkins] cpython (merge default -> default): merge heads

benjamin.peterson python-checkins at python.org
Fri Jul 15 22:23:10 CEST 2011


http://hg.python.org/cpython/rev/cd43d57f64db
changeset:   71364:cd43d57f64db
parent:      71363:f8199dea7ed3
parent:      71362:86dc49fbf4af
user:        Benjamin Peterson <benjamin at python.org>
date:        Fri Jul 15 15:27:58 2011 -0500
summary:
  merge heads

files:
  Lib/multiprocessing/process.py |   5 ++
  Lib/test/regrtest.py           |  37 +++++++++++++++++++++-
  Lib/test/test_descr.py         |   8 ++++
  Lib/threading.py               |   4 ++
  Misc/NEWS                      |   5 ++
  Objects/typeobject.c           |   2 +-
  6 files changed, 59 insertions(+), 2 deletions(-)


diff --git a/Lib/multiprocessing/process.py b/Lib/multiprocessing/process.py
--- a/Lib/multiprocessing/process.py
+++ b/Lib/multiprocessing/process.py
@@ -42,6 +42,7 @@
 import sys
 import signal
 import itertools
+from _weakrefset import WeakSet
 
 #
 #
@@ -109,6 +110,7 @@
         self._kwargs = dict(kwargs)
         self._name = name or type(self).__name__ + '-' + \
                      ':'.join(str(i) for i in self._identity)
+        _dangling.add(self)
 
     def run(self):
         '''
@@ -344,3 +346,6 @@
 for name, signum in list(signal.__dict__.items()):
     if name[:3]=='SIG' and '_' not in name:
         _exitcode_to_name[-signum] = name
+
+# For debug and leak testing
+_dangling = WeakSet()
diff --git a/Lib/test/regrtest.py b/Lib/test/regrtest.py
--- a/Lib/test/regrtest.py
+++ b/Lib/test/regrtest.py
@@ -182,6 +182,15 @@
 import warnings
 from inspect import isabstract
 
+try:
+    import threading
+except ImportError:
+    threading = None
+try:
+    import multiprocessing.process
+except ImportError:
+    multiprocessing = None
+
 
 # Some times __path__ and __file__ are not absolute (e.g. while running from
 # Lib/) and, if we change the CWD to run the tests in a temporary dir, some
@@ -930,7 +939,8 @@
                  'os.environ', 'sys.path', 'sys.path_hooks', '__import__',
                  'warnings.filters', 'asyncore.socket_map',
                  'logging._handlers', 'logging._handlerList', 'sys.gettrace',
-                 'sys.warnoptions')
+                 'sys.warnoptions', 'threading._dangling',
+                 'multiprocessing.process._dangling')
 
     def get_sys_argv(self):
         return id(sys.argv), sys.argv, sys.argv[:]
@@ -1023,6 +1033,31 @@
         sys.warnoptions = saved_options[1]
         sys.warnoptions[:] = saved_options[2]
 
+    # Controlling dangling references to Thread objects can make it easier
+    # to track reference leaks.
+    def get_threading__dangling(self):
+        if not threading:
+            return None
+        # This copies the weakrefs without making any strong reference
+        return threading._dangling.copy()
+    def restore_threading__dangling(self, saved):
+        if not threading:
+            return
+        threading._dangling.clear()
+        threading._dangling.update(saved)
+
+    # Same for Process objects
+    def get_multiprocessing_process__dangling(self):
+        if not multiprocessing:
+            return None
+        # This copies the weakrefs without making any strong reference
+        return multiprocessing.process._dangling.copy()
+    def restore_multiprocessing_process__dangling(self, saved):
+        if not multiprocessing:
+            return
+        multiprocessing.process._dangling.clear()
+        multiprocessing.process._dangling.update(saved)
+
     def resource_info(self):
         for name in self.resources:
             method_suffix = name.replace('.', '_')
diff --git a/Lib/test/test_descr.py b/Lib/test/test_descr.py
--- a/Lib/test/test_descr.py
+++ b/Lib/test/test_descr.py
@@ -4247,6 +4247,14 @@
         with self.assertRaises(TypeError):
             str.__add__(fake_str, "abc")
 
+    def test_repr_as_str(self):
+        # Issue #11603: crash or infinite loop when rebinding __str__ as
+        # __repr__.
+        class Foo:
+            pass
+        Foo.__repr__ = Foo.__str__
+        foo = Foo()
+        str(foo)
 
 class DictProxyTests(unittest.TestCase):
     def setUp(self):
diff --git a/Lib/threading.py b/Lib/threading.py
--- a/Lib/threading.py
+++ b/Lib/threading.py
@@ -6,6 +6,7 @@
 from time import time as _time, sleep as _sleep
 from traceback import format_exc as _format_exc
 from collections import deque
+from _weakrefset import WeakSet
 
 # Note regarding PEP 8 compliant names
 #  This threading model was originally inspired by Java, and inherited
@@ -608,6 +609,8 @@
 _active = {}    # maps thread id to Thread object
 _limbo = {}
 
+# For debug and leak testing
+_dangling = WeakSet()
 
 # Main class for threads
 
@@ -645,6 +648,7 @@
         # sys.stderr is not stored in the class like
         # sys.exc_info since it can be changed between instances
         self._stderr = _sys.stderr
+        _dangling.add(self)
 
     def _reset_internal_locks(self):
         # private!  Called by _after_fork() to reset our internal locks as
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -228,6 +228,9 @@
 Library
 -------
 
+- Issue #11603: Fix a crash when __str__ is rebound as __repr__.  Patch by
+  Andreas Stührk.
+
 - Issue #11321: Fix a crash with multiple imports of the _pickle module when
   embedding Python.  Patch by Andreas Stührk.
 
@@ -1033,6 +1036,8 @@
 Tests
 -----
 
+- Issue #12573: Add resource checks for dangling Thread and Process objects.
+
 - Issue #12549: Correct test_platform to not fail when OS X returns 'x86_64'
   as the processor type on some Mac systems.
 
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -2968,7 +2968,7 @@
     unaryfunc f;
 
     f = Py_TYPE(self)->tp_repr;
-    if (f == NULL)
+    if (f == NULL || f == object_str)
         f = object_repr;
     return f(self);
 }

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list