Подтвердить что ты не робот

Dump stacktraces всех активных потоков

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

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

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

Cheers,  Chriss

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

Как указывает дрожание в более раннем ответе 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"

Ответ 3

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

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

for th in threading.enumerate():
    print(th)
    traceback.print_stack(sys._current_frames()[th.ident])
    print()

Ответ 5

Просто для полноты, Products.LongRequestLogger очень полезно идентифицировать узкие места, и для этого он сбрасывает stacktraces через определенные промежутки времени.

Ответ 6

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