From 810f557514c60658f845dde716585eaad3e2bb4e Mon Sep 17 00:00:00 2001 From: David Wilson Date: Wed, 18 Apr 2018 23:37:42 +0100 Subject: [PATCH] issue #195: MITOGEN_DUMP_THREAD_STACKS=1 --- ansible_mitogen/services.py | 3 +++ mitogen/core.py | 1 + mitogen/debug.py | 33 +++++++++++++++++++-------------- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/ansible_mitogen/services.py b/ansible_mitogen/services.py index 6e7d4b5a..61f7477d 100644 --- a/ansible_mitogen/services.py +++ b/ansible_mitogen/services.py @@ -245,6 +245,9 @@ class ContextService(mitogen.service.Service): # We don't need to wait for the result of this. Ideally we'd check its # return value somewhere, but logs will catch a failure anyway. context.call_async(ansible_mitogen.target.start_fork_parent) + if os.environ.get('MITOGEN_DUMP_THREAD_STACKS'): + import mitogen.debug + context.call(mitogen.debug.dump_to_logger) self._key_by_context[context] = key self._refs_by_context[context] = 0 return { diff --git a/mitogen/core.py b/mitogen/core.py index 6bda7f84..20f52554 100644 --- a/mitogen/core.py +++ b/mitogen/core.py @@ -507,6 +507,7 @@ class Importer(object): self._context = context self._present = {'mitogen': [ 'compat', + 'debug', 'fakessh', 'fork', 'master', diff --git a/mitogen/debug.py b/mitogen/debug.py index 8cb1a367..eab1bef8 100644 --- a/mitogen/debug.py +++ b/mitogen/debug.py @@ -31,6 +31,7 @@ Basic signal handler for dumping thread stacks. """ import difflib +import logging import os import signal import sys @@ -39,6 +40,7 @@ import time import traceback +LOG = logging.getLogger(__name__) _last = None @@ -74,15 +76,13 @@ def format_stacks(): return '\n'.join(l) -def _handler(*_): +def get_snapshot(): global _last s = format_stacks() - fp = open('/dev/tty', 'w', 1) - fp.write(s) - + snap = s if _last: - fp.write('\n') + snap += '\n' diff = list(difflib.unified_diff( a=_last.splitlines(), b=s.splitlines(), @@ -91,25 +91,30 @@ def _handler(*_): )) if diff: - fp.write('\n'.join(diff) + '\n') + snap += '\n'.join(diff) + '\n' else: - fp.write('(no change since last time)\n') + snap += '(no change since last time)\n' _last = s + return snap + + +def _handler(*_): + fp = open('/dev/tty', 'w', 1) + fp.write(get_snapshot()) + fp.close() def install_handler(): signal.signal(signal.SIGUSR2, _handler) -def _thread_main(): +def _logging_main(): while True: - time.sleep(7) - l = format_stacks() - open('/tmp/stack.%s.log' % (os.getpid(),), 'wb', 65535).write(l) - break + time.sleep(5) + LOG.info('PERIODIC THREAD DUMP\n\n%s', get_snapshot()) -def dump_periodically(): - th = threading.Thread(target=main) +def dump_to_logger(): + th = threading.Thread(target=_logging_main) th.setDaemon(True) th.start()