From 7134c0bb05b29a16127b634d9ac253b457f137cb Mon Sep 17 00:00:00 2001 From: Bastian Kleineidam Date: Tue, 22 Jan 2013 18:16:53 +0100 Subject: [PATCH] Print thread stack traces on SIGUSR1 --- doc/changelog.txt | 2 ++ linkcheck/__init__.py | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/doc/changelog.txt b/doc/changelog.txt index 4581e9df..fefa3ea3 100644 --- a/doc/changelog.txt +++ b/doc/changelog.txt @@ -2,6 +2,8 @@ Features: - checking: Support URLs. +- logging: Sending SIGUSR1 signal prints the stack trace of all current + running threads. This makes it easier to debug deadlocks. Fixes: - checking: Fix a crash when closing a Word document after scanning failed. diff --git a/linkcheck/__init__.py b/linkcheck/__init__.py index 1364b41f..3c704886 100644 --- a/linkcheck/__init__.py +++ b/linkcheck/__init__.py @@ -32,6 +32,8 @@ if _dnspath not in sys.path: sys.path.insert(0, _dnspath) del _dnspath import re +import signal +import traceback from . import i18n import _LinkChecker_configdata as configdata @@ -176,3 +178,19 @@ def find_third_party_modules (): sys.path.append(os.path.join(third_party, "dnspython")) find_third_party_modules() + +# install SIGUSR1 handler +from .decorators import signal_handler +@signal_handler(signal.SIGUSR1) +def print_threadstacks(sig, frame): + """Print stack traces of all running threads.""" + log.warn(LOG_THREAD, "*** STACKTRACE START ***") + for threadId, stack in sys._current_frames().items(): + log.warn(LOG_THREAD, "# ThreadID: %s" % threadId) + for filename, lineno, name, line in traceback.extract_stack(stack): + log.warn(LOG_THREAD, 'File: "%s", line %d, in %s' % (filename, lineno, name)) + line = line.strip() + if line: + log.warn(LOG_THREAD, " %s" % line) + log.warn(LOG_THREAD, "*** STACKTRACE END ***") +