Дамп стека следов всех активных потоков - PullRequest
28 голосов
/ 23 июня 2009

Я пытаюсь вывести список всех активных потоков, включая текущий стек каждого. Я могу получить список всех потоков, используя threading.enumerate (), но я не могу найти способ добраться до стека оттуда.

Справочная информация. Время от времени выходит приложение Zope / Plone, потребляющее 100% процессорного времени, и его необходимо перезапустить. У меня такое ощущение, что это цикл, который не завершается должным образом, но я не могу воспроизвести его в test-environemt для проверки. Мне удалось зарегистрировать обработчик сигнала, который может быть запущен извне, так что я могу вызвать некоторый код, как только ситуация повторяется. Если бы я мог сбросить трассировку стека для всех активных потоков, это дало бы мне понять, что идет не так. Дырочка работает на питоне 2.4 ...

Любые идеи о том, как отследить подобные ситуации, приветствуются:)

Ура, Chriss

Ответы [ 6 ]

39 голосов
/ 06 сентября 2011

Как указывает джиттер в предыдущем ответе sys._current_frames() дает вам то, что вам нужно для v2.5 +. Для ленивых следующий фрагмент кода работал для меня и может помочь вам:

print >> sys.stderr, "\n*** STACKTRACE - START ***\n"
code = []
for threadId, stack in sys._current_frames().items():
    code.append("\n# ThreadID: %s" % threadId)
    for filename, lineno, name, line in traceback.extract_stack(stack):
        code.append('File: "%s", line %d, in %s' % (filename,
                                                    lineno, name))
        if line:
            code.append("  %s" % (line.strip()))

for line in code:
    print >> sys.stderr, line
print >> sys.stderr, "\n*** STACKTRACE - END ***\n"
19 голосов
/ 20 июня 2014

Для Python 3.3 и более поздних версий есть faulthandler.dump_traceback().

Приведенный ниже код производит аналогичные выходные данные, но включает имя потока и может быть улучшен для печати дополнительной информации.

for th in threading.enumerate():
    print(th)
    traceback.print_stack(sys._current_frames()[th.ident])
    print()
10 голосов
/ 24 июня 2009

При использовании Zope вы хотите установить Products.signalstack или mr.freeze ; они были разработаны именно для этой цели!

Отправьте сигнал USR1 на ваш сервер Zope, и он немедленно сбросит следы стека для всех потоков на консоль. Это будет сделано, даже если все потоки Zope заблокированы.

Под капотом эти пакеты косвенно используют threadframes; для Python версий 2.5 и выше, когда не с использованием Zope, вы можете создать ту же функциональность, используя функцию sys._current_frames() для доступа к фреймам стека для каждого потока.

Начиная с Zope 2.12.5 эта функциональность интегрирована в сам Zope, и больше нет необходимости устанавливать дополнительные пакеты.

7 голосов
/ 23 июня 2009

2,4. Очень плохо. Начиная с версии 2.5, sys._current_frames().

Но вы можете попробовать threadframe . И если makefile доставляет вам неприятности, вы можете попробовать этот setup.py для потокового кадра

Пример вывода при использовании потокового кадра

1 голос
/ 01 ноября 2015

Только для полноты, Products.LongRequestLogger очень полезен для выявления узких мест и для этого сбрасывает трассировки стека через определенные интервалы.

0 голосов
/ 23 июня 2009

На ASPN имеется соответствующий рецепт. Вы можете использовать threading.enumerate() для получения всех приливов, а затем просто вызвать _async_raise () с некоторым подходящим исключением, чтобы вызвать трассировку стека.

...