]> granicus.if.org Git - python/commitdiff
Issue #6615: logging: Used weak references in internal handler list. Thanks to flox...
authorVinay Sajip <vinay_sajip@yahoo.co.uk>
Wed, 25 Nov 2009 09:03:30 +0000 (09:03 +0000)
committerVinay Sajip <vinay_sajip@yahoo.co.uk>
Wed, 25 Nov 2009 09:03:30 +0000 (09:03 +0000)
Lib/logging/__init__.py
Misc/NEWS

index 5b8cb4ec9744ba5bf5e22b38a9e94cea065916cd..f5dfc39b644b6abf94e7bc9eb3f3cf07c6a8b5af 100644 (file)
@@ -23,7 +23,7 @@ Copyright (C) 2001-2009 Vinay Sajip. All Rights Reserved.
 To use, simply 'import logging' and log away!
 """
 
-import sys, os, time, cStringIO, traceback, warnings
+import sys, os, time, cStringIO, traceback, warnings, weakref
 
 __all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR',
            'FATAL', 'FileHandler', 'Filter', 'Formatter', 'Handler', 'INFO',
@@ -46,8 +46,8 @@ except ImportError:
 
 __author__  = "Vinay Sajip <vinay_sajip@red-dove.com>"
 __status__  = "production"
-__version__ = "0.5.1.0"
-__date__    = "24 November 2009"
+__version__ = "0.5.1.1"
+__date__    = "25 November 2009"
 
 #---------------------------------------------------------------------------
 #   Miscellaneous module data
@@ -593,6 +593,27 @@ class Filterer(object):
 _handlers = {}  #map of handler names to handlers
 _handlerList = [] # added to allow handlers to be removed in reverse of order initialized
 
+def _removeHandlerRef(wr):
+    """
+    Remove a handler reference from the internal cleanup list.
+    """
+    _acquireLock()
+    try:
+        if wr in _handlerList:
+            _handlerList.remove(wr)
+    finally:
+        _releaseLock()
+
+def _addHandlerRef(handler):
+    """
+    Add a handler to the internal cleanup list using a weak reference.
+    """
+    _acquireLock()
+    try:
+        _handlerList.insert(0, weakref.ref(handler, _removeHandlerRef))
+    finally:
+        _releaseLock()
+
 class Handler(Filterer):
     """
     Handler instances dispatch logging events to specific destinations.
@@ -611,12 +632,8 @@ class Handler(Filterer):
         self._name = None
         self.level = _checkLevel(level)
         self.formatter = None
-        #get the module data lock, as we're updating a shared structure.
-        _acquireLock()
-        try:    #unlikely to raise an exception, but you never know...
-            _handlerList.insert(0, self)
-        finally:
-            _releaseLock()
+        # Add the handler to the global _handlerList (for cleanup on shutdown)
+        _addHandlerRef(self)
         self.createLock()
 
     def get_name(self):
@@ -724,8 +741,8 @@ class Handler(Filterer):
         """
         Tidy up any resources used by the handler.
 
-        This version does removes the handler from an internal list
-        of handlers which is closed when shutdown() is called. Subclasses
+        This version removes the handler from an internal map of handlers,
+        _handlers, which is used for handler lookup by name. Subclasses
         should ensure that this gets called from overridden close()
         methods.
         """
@@ -734,7 +751,6 @@ class Handler(Filterer):
         try:    #unlikely to raise an exception, but you never know...
             if self._name and self._name in _handlers:
                 del _handlers[self._name]
-            _handlerList.remove(self)
         finally:
             _releaseLock()
 
@@ -1532,10 +1548,11 @@ def shutdown(handlerList=_handlerList):
 
     Should be called at application exit.
     """
-    for h in handlerList[:]:
+    for wr in reversed(handlerList[:]):
         #errors might occur, for example, if files are locked
         #we just ignore them if raiseExceptions is not set
         try:
+            h = wr()
             h.flush()
             h.close()
         except:
index d582e39fdbd02f6200e7b64f5f97f5ae2cdeb64b..b9a16ee1a32f57df3777b39ee06a7395232ebfeb 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -483,12 +483,14 @@ Core and Builtins
 Library
 -------
 
+- Issue #6615: logging: Used weakrefs in internal handler list.
+
 - Issue #1488943: difflib.Differ() doesn't always add hints for tab characters
 
 - Issue #6123: tarfile now opens empty archives correctly and consistently
   raises ReadError on empty files.
 
-- Issue #7354: distutils.tests.test_msvc9compiler - dragfullwindows can 
+- Issue #7354: distutils.tests.test_msvc9compiler - dragfullwindows can
   be 2.
 
 - Issue #5037: Proxy the __unicode__ special method instead to __unicode__
@@ -563,7 +565,7 @@ Library
 - Issue #7071: byte-compilation in Distutils is now done with respect to
   sys.dont_write_bytecode.
 
-- Issue #7066: archive_util.make_archive now restores the cwd if an error is 
+- Issue #7066: archive_util.make_archive now restores the cwd if an error is
   raised. Initial patch by Ezio Melotti.
 
 - Issue #6218: io.StringIO and io.BytesIO instances are now picklable with