Dump stacktraces всех активных потоков
Я пытаюсь сбрасывать список всех активных потоков, включая текущий стек каждого. Я могу получить список всех потоков, используя threading.enumerate(), но я не могу найти способ добраться до стека оттуда.
Справочная информация. Приложение Zope/Plone время от времени изматывается, потребляя 100% процессора и его необходимо перезапустить. У меня есть ощущение, что это цикл, который не заканчивается должным образом, но я не могу воспроизвести его в test-environemt для проверки. Мне удалось зарегистрировать обработчик сигналов, который может запускаться извне, поэтому я могу запустить некоторый код, как только ситуация повторится. Если бы я мог сбросить стек для всех активных потоков, это дало бы мне понять, что происходит не так. Ядро работает на python 2.4...
Любые идеи о том, как отслеживать подобные ситуации, оцениваются:)
Cheers, Chriss
Ответы
Ответ 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()
Ответ 4
2,4. Очень жаль. Из Python 2.5 существует sys._current_frames()
.
Но вы можете попробовать threadframe. И если make файл дает вам проблемы, вы можете попробовать этот setup.py для файловой рамки
Пример вывода при использовании файловой рамки
Ответ 5
Просто для полноты, Products.LongRequestLogger очень полезно идентифицировать узкие места, и для этого он сбрасывает stacktraces через определенные промежутки времени.
Ответ 6
Существует соответствующий рецепт ASPN. Вы можете использовать threading.enumerate()
для получения всех тидов, а затем просто вызовите _async_raise() с некоторым подходящим исключением, чтобы заставить трассировку стека.