[Zope-Checkins] SVN: Zope/trunk/ Integrated the Products.signalstack / z3c.deadlockdebugger packages. You can now send a SIGUSR1 signal to a Zope process and get a stack trace of all threads printed out on the console. This works even if all threads are stuck.

Hanno Schlichting hannosch at hannosch.eu
Tue Mar 30 15:47:54 EDT 2010


Log message for revision 110336:
  Integrated the Products.signalstack / z3c.deadlockdebugger packages. You can now send a SIGUSR1 signal to a Zope process and get a stack trace of all threads printed out on the console. This works even if all threads are stuck.
  

Changed:
  U   Zope/trunk/doc/CHANGES.rst
  U   Zope/trunk/src/Signals/Signals.py
  A   Zope/trunk/src/Signals/threads.py

-=-
Modified: Zope/trunk/doc/CHANGES.rst
===================================================================
--- Zope/trunk/doc/CHANGES.rst	2010-03-30 18:29:02 UTC (rev 110335)
+++ Zope/trunk/doc/CHANGES.rst	2010-03-30 19:47:54 UTC (rev 110336)
@@ -83,6 +83,13 @@
 Features Added
 ++++++++++++++
 
+- Integrated the Products.signalstack / z3c.deadlockdebugger packages. You can
+  now send a SIGUSR1 signal to a Zope process and get a stack trace of all
+  threads printed out on the console. This works even if all threads are stuck.
+
+- ZCTextIndex query parser treats fullwidth space characters defined
+  in Unicode as valid white space.
+
 - Updated packages:
 
   - initgroups = 2.13.0
@@ -119,9 +126,6 @@
   - zope.traversing = 3.12.0
   - zope.viewlet = 3.7.0
 
-- ZCTextIndex query parser treats fullwidth space characters defined
-  in Unicode as valid white space.
-
 Bugs Fixed
 ++++++++++
 

Modified: Zope/trunk/src/Signals/Signals.py
===================================================================
--- Zope/trunk/src/Signals/Signals.py	2010-03-30 18:29:02 UTC (rev 110335)
+++ Zope/trunk/src/Signals/Signals.py	2010-03-30 19:47:54 UTC (rev 110336)
@@ -18,10 +18,14 @@
 __version__='$Revision: 1.3 $'[11:-2]
 
 import logging
-import sys, os
+import os
+import sys
 
 import Lifetime
 
+from .threads import dump_threads
+
+
 logger = logging.getLogger("Z2")
 
 if os.name == 'nt':
@@ -55,6 +59,13 @@
     logger.info("Restarting")
     Lifetime.shutdown(1)
 
+
+def showStacks():
+    """Dump a stracktrace of all threads on the console."""
+    print dump_threads()
+    sys.stdout.flush()
+
+
 class LogfileReopenHandler:
     """Reopen log files on SIGUSR2.
 
@@ -104,6 +115,7 @@
     SignalHandler.registerHandler(SIGINT, shutdownHandler)
     if os.name != 'nt':
         SignalHandler.registerHandler(SIGHUP, restartHandler)
+        SignalHandler.registerHandler(SIGUSR1, showStacks)
         SignalHandler.registerHandler(SIGUSR2, LogfileReopenHandler(loggers))
     else:
         # no restart handler on windows.

Copied: Zope/trunk/src/Signals/threads.py (from rev 110335, z3c.deadlockdebugger/trunk/z3c/deadlockdebugger/threads.py)
===================================================================
--- Zope/trunk/src/Signals/threads.py	                        (rev 0)
+++ Zope/trunk/src/Signals/threads.py	2010-03-30 19:47:54 UTC (rev 110336)
@@ -0,0 +1,45 @@
+import sys
+import thread
+import traceback
+import time
+from cStringIO import StringIO
+
+
+def dump_threads():
+    """Dump running threads. Returns a string with the tracebacks."""
+
+    frames = sys._current_frames()
+    this_thread_id = thread.get_ident()
+    now = time.strftime("%Y-%m-%d %H:%M:%S")
+    res = ["Threads traceback dump at %s\n" % now]
+    for thread_id, frame in frames.iteritems():
+        if thread_id == this_thread_id:
+            continue
+
+        # Find request in frame
+        reqinfo = ''
+        f = frame
+        while f is not None:
+            co = f.f_code
+            if co.co_name == 'publish':
+                if co.co_filename.endswith('/ZPublisher/Publish.py'):
+                    request = f.f_locals.get('request')
+                    if request is not None:
+                        reqinfo += (request.get('REQUEST_METHOD', '') + ' ' +
+                                   request.get('PATH_INFO', ''))
+                        qs = request.get('QUERY_STRING')
+                        if qs:
+                            reqinfo += '?'+qs
+                    break
+            f = f.f_back
+        if reqinfo:
+            reqinfo = " (%s)" % reqinfo
+
+        output = StringIO()
+        traceback.print_stack(frame, file=output)
+        res.append("Thread %s%s:\n%s" %
+            (thread_id, reqinfo, output.getvalue()))
+
+    frames = None
+    res.append("End of dump")
+    return '\n'.join(res)



More information about the Zope-Checkins mailing list