Author: dmeyer
Date: Tue Feb 12 10:36:10 2008
New Revision: 3049

Log:
log exception without using __del__

Modified:
   trunk/base/src/notifier/async.py
   trunk/base/src/notifier/yieldfunc.py

Modified: trunk/base/src/notifier/async.py
==============================================================================
--- trunk/base/src/notifier/async.py    (original)
+++ trunk/base/src/notifier/async.py    Tue Feb 12 10:36:10 2008
@@ -35,10 +35,11 @@
 import logging
 import traceback
 import time
+import _weakref
 import threading
 
 # kaa.notifier imports
-from callback import Signal
+from callback import Signal, Callback
 
 # get logging object
 log = logging.getLogger('notifier.async')
@@ -108,14 +109,9 @@
         self.exception = Signal()
         self._finished = False
         self._finished_event = threading.Event()
-        self._unhandled_exception = False
+        self._unhandled_exception = None
         self.status = None
 
-    def __del__(self):
-        if self._unhandled_exception:
-            # We didn't get a chance to log this unhandled exception, so do
-            # it now.
-            self._log_exception()
 
     def set_status(self, s):
         """
@@ -168,27 +164,34 @@
         # store result
         self._finished = True
         self._exception = type, value, tb
-        self._unhandled_exception = False
+        self._unhandled_exception = None
         # Wake any threads waiting on us
         self._finished_event.set()
 
         if self.exception.emit_when_handled(type, value, tb) != False:
             # No handler returned False to block us from logging the exception.
             # Set a flag to log the exception in the destructor if it is
-            # not raised with get_result().
-            self._unhandled_exception = True
+            # not raised with get_result(). Using a nornal Python destructor
+            # does not work because it would be too easy to create a circular
+            # reference with InProgress and yield_execution which would result
+            # in a memory leak. Since we do not need the InProgress object to
+            # log the unhandled exception, a weakref callback is used. So this
+            # is __del__ without using __del__.
+            trace = 
''.join(traceback.format_exception(*self._exception)).strip()
+            cb = Callback(InProgress._log_exception, trace)
+            self._unhandled_exception = _weakref.ref(self, cb)
 
         # cleanup
         self.disconnect_all()
         self.exception.disconnect_all()
 
 
-    def _log_exception(self):
-        if not self._unhandled_exception:
-            return
-        self._unhandled_exception = False
-        trace = ''.join(traceback.format_exception(*self._exception)).strip()
-        log.error('*** Unhandled %s exception ***\n%s', 
self.__class__.__name__, trace)
+    @classmethod
+    def _log_exception(cls, weakref, trace):
+        """
+        Callback to log unhandled exceptions.
+        """
+        log.error('*** Unhandled %s exception ***\n%s', cls.__name__, trace)
 
 
     def __call__(self, *args, **kwargs):
@@ -217,7 +220,7 @@
         if not self._finished:
             raise RuntimeError('operation not finished')
         if self._exception:
-            self._unhandled_exception = False
+            self._unhandled_exception = None
             type, value, tb = self._exception
             # Special 3-argument form of raise; preserves traceback
             raise type, value, tb

Modified: trunk/base/src/notifier/yieldfunc.py
==============================================================================
--- trunk/base/src/notifier/yieldfunc.py        (original)
+++ trunk/base/src/notifier/yieldfunc.py        Tue Feb 12 10:36:10 2008
@@ -132,7 +132,7 @@
     """
     if _python25 and async is not None:
         if async._exception:
-            async._unhandled_exception = False
+            async._unhandled_exception = None
             return func.throw(*async._exception)
         return func.send(async._result)
     return func.next()

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Freevo-cvslog mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/freevo-cvslog

Reply via email to