Implement stack trace dump for all running threads on SIGQUIT

This is handy when we're debugging the thread locks: we can try to
understand which thread does what and how it was called.

Signed-off-by: Eygene Ryabinkin <rea@codelabs.ru>
This commit is contained in:
Eygene Ryabinkin
2013-01-28 22:49:29 +04:00
parent 83e8fca2e0
commit de84c3941c
4 changed files with 36 additions and 2 deletions

View File

@ -28,6 +28,7 @@ from offlineimap import accounts, threadutil, syncmaster
from offlineimap.error import OfflineImapError
from offlineimap.ui import UI_LIST, setglobalui, getglobalui
from offlineimap.CustomConfig import CustomConfigParser
from offlineimap.utils import stacktrace
class OfflineImap:
@ -341,12 +342,16 @@ class OfflineImap:
getglobalui().warn("Terminating NOW (this may "\
"take a few seconds)...")
accounts.Account.set_abort_event(self.config, 3)
elif sig == signal.SIGQUIT:
stacktrace.dump (sys.stderr)
os.abort()
signal.signal(signal.SIGHUP,sig_handler)
signal.signal(signal.SIGUSR1,sig_handler)
signal.signal(signal.SIGUSR2,sig_handler)
signal.signal(signal.SIGTERM, sig_handler)
signal.signal(signal.SIGINT, sig_handler)
signal.signal(signal.SIGQUIT, sig_handler)
#various initializations that need to be performed:
offlineimap.mbnames.init(self.config, syncaccounts)

View File

@ -0,0 +1,25 @@
# Copyright 2013 Eygene A. Ryabinkin
# Functions to perform stack tracing (for multithreaded programs
# as well as for single-threaded ones).
import sys
import threading
import traceback
def dump(out):
""" Dumps current stack trace into I/O object 'out' """
id2name = {}
for th in threading.enumerate():
id2name[th.ident] = th.name
n = 0
for i, stack in sys._current_frames().items():
out.write ("\n# Thread #%d (id=%d), %s\n" % \
(n, i, id2name[i]))
n = n + 1
for f, lno, name, line in traceback.extract_stack (stack):
out.write ('File: "%s", line %d, in %s' % \
(f, lno, name))
if line:
out.write (" %s" % (line.strip()))
out.write ("\n")