[Checkins] SVN: zope.server/trunk/ Exceptions that happen in the handler thread main loop are logged now.

Marius Gedminas cvs-admin at zope.org
Wed May 30 22:52:50 UTC 2012


Log message for revision 126528:
  Exceptions that happen in the handler thread main loop are logged now.
  
  I spent two days figuring out why my server started losing threads, until
  I pinned it down to a buggy logging handler.

Changed:
  U   zope.server/trunk/CHANGES.txt
  U   zope.server/trunk/src/zope/server/taskthreads.py
  A   zope.server/trunk/src/zope/server/tests/test_taskthreads.py

-=-
Modified: zope.server/trunk/CHANGES.txt
===================================================================
--- zope.server/trunk/CHANGES.txt	2012-05-30 20:08:30 UTC (rev 126527)
+++ zope.server/trunk/CHANGES.txt	2012-05-30 22:52:46 UTC (rev 126528)
@@ -10,7 +10,10 @@
 
 - Dropped support for Python 2.4 and 2.5.
 
+- Exceptions that happen in the handler thread main loop are logged so that
+  the unexpected death of a handler thread does not happen in silence.
 
+
 3.8.6 (2012-01-07)
 ------------------
 

Modified: zope.server/trunk/src/zope/server/taskthreads.py
===================================================================
--- zope.server/trunk/src/zope/server/taskthreads.py	2012-05-30 20:08:30 UTC (rev 126527)
+++ zope.server/trunk/src/zope/server/taskthreads.py	2012-05-30 22:52:46 UTC (rev 126528)
@@ -48,6 +48,8 @@
                     task.service()
                 except:
                     log.exception('Exception during task')
+        except:
+            log.exception('Exception in thread main loop')
         finally:
             mlock = self.thread_mgmt_lock
             mlock.acquire()

Added: zope.server/trunk/src/zope/server/tests/test_taskthreads.py
===================================================================
--- zope.server/trunk/src/zope/server/tests/test_taskthreads.py	                        (rev 0)
+++ zope.server/trunk/src/zope/server/tests/test_taskthreads.py	2012-05-30 22:52:46 UTC (rev 126528)
@@ -0,0 +1,70 @@
+import doctest
+import logging
+from cStringIO import StringIO
+
+from zope.server.taskthreads import ThreadedTaskDispatcher
+
+
+class CountingDict(dict):
+    """A dict that decrements values on every .get()"""
+
+    def get(self, key, default=None):
+        value = dict.get(self, key, default)
+        if key in self:
+            self[key] -= 1
+        return value
+
+class QueueStub(object):
+    def __init__(self, items=()):
+        self.items = list(items)
+    def get(self):
+        return self.items.pop(0)
+
+class TaskStub(object):
+    def service(self):
+        raise Exception('testing exception handling')
+
+
+def setUp(test):
+    test.logger = logging.getLogger('zope.server.taskthreads')
+    test.logbuf = StringIO()
+    test.good_handler = logging.StreamHandler(test.logbuf)
+    test.logger.addHandler(test.good_handler)
+    test.bad_handler = logging.Handler()
+    # test.bad_handler.emit() raises, which is what we want
+    test.logger.addHandler(test.bad_handler)
+    test.globs['logbuf'] = test.logbuf
+
+def tearDown(test):
+    test.logger.removeHandler(test.bad_handler)
+    test.logger.removeHandler(test.good_handler)
+
+
+def doctest_handlerThread_logs_exceptions_that_happen_during_exception_logging():
+    """Test that ThreadedTaskDispatcher.handlerThread doesn't terminate silently
+
+        >>> dispatcher = ThreadedTaskDispatcher()
+        >>> dispatcher.threads = CountingDict({42: 1})
+        >>> dispatcher.queue = QueueStub([TaskStub()])
+        >>> try: dispatcher.handlerThread(42)
+        ... except: pass
+
+    It's important that exceptions in the thread main loop get logged, not just
+    exceptions that happen while handling tasks
+
+        >>> print logbuf.getvalue(), # doctest: +ELLIPSIS
+        Exception during task
+        Traceback (most recent call last):
+          ...
+        Exception: testing exception handling
+        Exception in thread main loop
+        Traceback (most recent call last):
+          ...
+        NotImplementedError: emit must be implemented by Handler subclasses
+
+    """
+
+
+def test_suite():
+    return doctest.DocTestSuite(setUp=setUp, tearDown=tearDown)
+


Property changes on: zope.server/trunk/src/zope/server/tests/test_taskthreads.py
___________________________________________________________________
Added: svn:keywords
   + Id



More information about the checkins mailing list