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:
parent
83e8fca2e0
commit
de84c3941c
@ -7,7 +7,8 @@ ChangeLog
|
|||||||
WIP (add new stuff for the next release)
|
WIP (add new stuff for the next release)
|
||||||
========================================
|
========================================
|
||||||
|
|
||||||
=======
|
* Dump stacktrace for all threads on SIGQUIT: ease debugging
|
||||||
|
of threading and other issues
|
||||||
* SIGHUP is now handled as the termination notification rather than
|
* SIGHUP is now handled as the termination notification rather than
|
||||||
the signal to reread the configuration (Dmitrijs Ledkovs)
|
the signal to reread the configuration (Dmitrijs Ledkovs)
|
||||||
* Honor the timezone of emails (Tobias Thierer)
|
* Honor the timezone of emails (Tobias Thierer)
|
||||||
|
@ -309,7 +309,7 @@ UNIX Signals
|
|||||||
============
|
============
|
||||||
|
|
||||||
OfflineImap listens to the unix signals SIGUSR1, SIGUSR2, SIGTERM,
|
OfflineImap listens to the unix signals SIGUSR1, SIGUSR2, SIGTERM,
|
||||||
SIGINT, SIGHUP:
|
SIGINT, SIGHUP, SIGQUIT:
|
||||||
|
|
||||||
If sent a SIGUSR1 it will abort any current (or next future) sleep of all
|
If sent a SIGUSR1 it will abort any current (or next future) sleep of all
|
||||||
accounts that are configured to "autorefresh". In effect, this will trigger a
|
accounts that are configured to "autorefresh". In effect, this will trigger a
|
||||||
@ -326,6 +326,9 @@ in each account, close keep alive connections, remove locks on the
|
|||||||
accounts and exit. It may take up to 10 seconds, if autorefresh option
|
accounts and exit. It may take up to 10 seconds, if autorefresh option
|
||||||
is used.
|
is used.
|
||||||
|
|
||||||
|
SIGQUIT dumps stack traces for all threads and tries to dump process
|
||||||
|
core.
|
||||||
|
|
||||||
Folder filtering and nametrans
|
Folder filtering and nametrans
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ from offlineimap import accounts, threadutil, syncmaster
|
|||||||
from offlineimap.error import OfflineImapError
|
from offlineimap.error import OfflineImapError
|
||||||
from offlineimap.ui import UI_LIST, setglobalui, getglobalui
|
from offlineimap.ui import UI_LIST, setglobalui, getglobalui
|
||||||
from offlineimap.CustomConfig import CustomConfigParser
|
from offlineimap.CustomConfig import CustomConfigParser
|
||||||
|
from offlineimap.utils import stacktrace
|
||||||
|
|
||||||
|
|
||||||
class OfflineImap:
|
class OfflineImap:
|
||||||
@ -341,12 +342,16 @@ class OfflineImap:
|
|||||||
getglobalui().warn("Terminating NOW (this may "\
|
getglobalui().warn("Terminating NOW (this may "\
|
||||||
"take a few seconds)...")
|
"take a few seconds)...")
|
||||||
accounts.Account.set_abort_event(self.config, 3)
|
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.SIGHUP,sig_handler)
|
||||||
signal.signal(signal.SIGUSR1,sig_handler)
|
signal.signal(signal.SIGUSR1,sig_handler)
|
||||||
signal.signal(signal.SIGUSR2,sig_handler)
|
signal.signal(signal.SIGUSR2,sig_handler)
|
||||||
signal.signal(signal.SIGTERM, sig_handler)
|
signal.signal(signal.SIGTERM, sig_handler)
|
||||||
signal.signal(signal.SIGINT, sig_handler)
|
signal.signal(signal.SIGINT, sig_handler)
|
||||||
|
signal.signal(signal.SIGQUIT, sig_handler)
|
||||||
|
|
||||||
#various initializations that need to be performed:
|
#various initializations that need to be performed:
|
||||||
offlineimap.mbnames.init(self.config, syncaccounts)
|
offlineimap.mbnames.init(self.config, syncaccounts)
|
||||||
|
25
offlineimap/utils/stacktrace.py
Normal file
25
offlineimap/utils/stacktrace.py
Normal 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")
|
Loading…
Reference in New Issue
Block a user