Получить трассировку стека из зависшего процесса Python

Мне нужно запустить устаревший веб-сайт Zope2 и у меня есть некоторые претензии к нему. Самая большая проблема заключается в том, что иногда он просто блокируется, работает со 100% загрузкой ЦП и больше не отвечает на запросы. Хотя проблема не воспроизводится на регулярной основе, одна страница, содержащая 3 динамических графика, иногда вызывает ее, поэтому я подозреваю, что какое-то состояние гонки приводит к бесконечному циклу или зависанию занятости.

Проблема в том, что я пока не нашел способ отладить эту штуку. Нет ничего в журналах Zope и ничего в журналах системы. Я попробовал предложения из этого вопроса, чтобы получить трассировку стека, но единственный сигнал, который имеет какое-либо влияние, - это SIGKILL.

Есть ли еще одна возможность узнать, где именно находится процесс, когда он застревает?


person Benjamin Wohlwend    schedule 23.11.2009    source источник


Ответы (5)


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

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

person abyx    schedule 23.11.2009

Вы можете распечатать красивую трассировку стека, используя pyrasite.

Во-первых, вам нужно установить gdb.

# Redhat, CentOS, etc
$ yum install gdb

# Ubuntu, Debian, etc
$ apt-get update && apt-get install gdb

Затем установите пиразит.

$ pip install pyrasite

Используйте ps или другой метод, чтобы найти идентификатор застрявшего процесса python и запустить с ним pyrasite-shell.

# Assuming process ID is 12345
$ pyrasite-shell 12345

Теперь вы должны увидеть REPL на Python. Выполните следующую команду в REPL, чтобы увидеть трассировки стека для всех потоков.

import sys, traceback
for thread_id, frame in sys._current_frames().items():
    print 'Stack for thread {}'.format(thread_id)
    traceback.print_stack(frame)
    print ''
person Sean    schedule 03.06.2017
comment
Когда я это делаю, пиразитовая оболочка тоже виснет - person Bhavani Ravi; 13.10.2020
comment
так же висит пиразитовый снаряд - person Nathan B; 07.03.2021
comment
вам нужно запустить pyrasite-shell с владельцем процесса - person Ping.Goblue; 12.06.2021

См. Мой ответ на этого SO вопрос, используйте Products.signalstack. Он регистрирует тот же обработчик, что и ответ, который вы уже нашли, во время регистрации продукта. Возможно, это сработает для вас лучше.

В противном случае у вас, вероятно, есть проблема ввода-вывода на уровне ОС, и ваша единственная надежда - подключить gdb к процессу. Найдите ответы на GDB в переполнении стека; здесь много информации!

person Martijn Pieters    schedule 23.11.2009

Вы можете попробовать подключить отладчик к запущенному процессу. См. Также этот вопрос.

person Thomas    schedule 23.11.2009

некоторое время бегая по Интернету кругами, я наконец оказался здесь: http://podoliaka.org/2016/04/10/debugging-cpython-gdb/ - подробно описывает, как все части сочетаются друг с другом. денежная квота для меня была «gdb / usr / bin / python -p $ PID» - имя исполняемого файла требуется для того, чтобы gdb мог найти правильные файлы отладочной информации.

person Baczek    schedule 26.09.2016