[Python-checkins] cpython (3.2): Issue #12573: Add resource checks for dangling Thread and Process objects.

antoine.pitrou python-checkins at python.org
Fri Jul 15 22:16:51 CEST 2011


http://hg.python.org/cpython/rev/2bedea96de60
changeset:   71361:2bedea96de60
branch:      3.2
parent:      71358:64e35f3bcda5
user:        Antoine Pitrou <solipsis at pitrou.net>
date:        Fri Jul 15 22:12:24 2011 +0200
summary:
  Issue #12573: Add resource checks for dangling Thread and Process objects.

files:
  Lib/multiprocessing/process.py |   5 ++
  Lib/test/regrtest.py           |  37 +++++++++++++++++++++-
  Lib/threading.py               |   4 ++
  Misc/NEWS                      |   2 +
  4 files changed, 47 insertions(+), 1 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
 
 #
 #
@@ -105,6 +106,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):
         '''
@@ -328,3 +330,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
@@ -172,6 +172,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
@@ -864,7 +873,8 @@
                  'os.environ', 'sys.path', 'sys.path_hooks', '__import__',
                  'warnings.filters', 'asyncore.socket_map',
                  'logging._handlers', 'logging._handlerList',
-                 'sys.warnoptions')
+                 'sys.warnoptions', 'threading._dangling',
+                 'multiprocessing.process._dangling')
 
     def get_sys_argv(self):
         return id(sys.argv), sys.argv, sys.argv[:]
@@ -952,6 +962,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/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
@@ -606,6 +607,8 @@
 _active = {}    # maps thread id to Thread object
 _limbo = {}
 
+# For debug and leak testing
+_dangling = WeakSet()
 
 # Main class for threads
 
@@ -640,6 +643,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
@@ -67,6 +67,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.
 

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


More information about the Python-checkins mailing list