Анализ gnome-shell с помощью Valgrind
Для того, чтобы с помощью Valgrind искать ошибки (утечки памяти, некорректные обращения к памяти, и т.п.) в gnome-shell нужно выполнить несколько не очень очевидных операций. Вот как всё делается.
Подготовка
Чтобы не набирать длинные команды каждый раз, полезно подготовить пару скриптов и положить их, скажем, в ~/bin/ на той системе, где нужно проверить gnome-shell.
xenv.sh - этот скрипт установит необходимые переменные окружения:
gnome_session=$(pgrep -u $USER gnome-session) eval export $(sed 's/\o000/\n/g;' < /proc/$gnome_session/environ | grep DISPLAY) eval export $(sed 's/\o000/\n/g;' < /proc/$gnome_session/environ | grep XAUTHORITY) eval export $(sed 's/\o000/\n/g;' < /proc/$gnome_session/environ | grep DBUS_SESSION_BUS_ADDRESS)
vg_gnome_shell.sh - этот скрипт запускает gnome-shell под Valgrind с нужными параметрами (подробности ниже):
G_SLICE=always-malloc G_DEBUG=gc-friendly valgrind --leak-check=full --show-reachable=yes \ --fullpath-after= --num-callers=40 --log-file=vg.log \ --suppressions=clutter-2.0.suppressions \ gnome-shell --replace
То, что Valgrind считает ошибками, - не всегда ошибки. Некоторые ложные сообщения об ошибках можно убрать, передав Valgrind'у при запуске файл(ы) с соотв. данными (suppression files).
В скрипте vg_gnome_shell.sh используется suppression file clutter-2.0.suppressions, предполагается, что он лежит в текущем каталоге.
Чтобы в call stack в отчёте Valgrind были указаны строки кода, а не просто адреса, стоит установить пакеты с отладочной информацией. Вот список с одной из систем, где проводится анализ gnome-shell:
gnome-shell-debuginfo gnome-desktop3-debuginfo gnome-session-debuginfo gnome-settings-daemon-debuginfo gnome-themes-standard-debuginfo gnome-utils-debuginfo gnome-vfs2-debuginfo gtk+3.0-debuginfo gtk-css-engine-debuginfo gtkmm3.0-debuginfo dbus-glib-debuginfo glib2.0-debuginfo glibc-debuginfo js-debuginfo pbmtozjs-debuginfo libjsw-debuginfo gjs-debuginfo json-glib-debuginfo libsvg-cairo-debuginfo cairo-dock-debuginfo gtkcairo-debuginfo librsvg-debuginfo cairo-debuginfo cairo-dock-plugins-debuginfo cairomm-debuginfo pixman-debuginfo cogl-debuginfo gegl-debuginfo mesa-debuginfo glew-debuginfo clutter-debuginfo clutter-gtk-debuginfo pango-debuginfo harfbuzz-debuginfo fontconfig-debuginfo mutter-debuginfo dconf-debuginfo
Какие-то из них, вероятно, не нужны, но кашу маслом не испортишь.
Запуск
Стоит залогиниться в системе, как обычно. Затем - перейти, например, в вирт. консоль №2 (ctrl-alt-f2) и залогиниться там тем же пользователем.
Теперь надо установить нужные переменные среды, используя подготовленный выше скрипт:
$ . ~/bin/xenv.sh
Соотв. переменные будут выставлены так же, как для данного пользователя они стоят в X11-сессии. Обратите внимание: точка перед ~/bin/xenv.sh нужна. Скрипт не выполняется в новом shell'е, а "source'ится" в текущий.
Если нужно для использовать suppression файлы для Valgrind, стоит проверить, что в vg_gnome_shell.sh правильно указаны пути к ним.
Теперь можно запускать gnome-shell под Valgrind.
$ sh ~/bin/vg_gnome_shell.sh
Запуск может занять несколько минут: Valgrind может достаточно сильно замедлить загрузку и работу анализируемого приложения. Когда gnome-shell выведет сообщение о том, что она запустилась, можно переключаться в вирт. консоль, где запущены X11. Вероятно, после этого придётся подождать ещё несколько минут пока там появится всё необходимое.
После этого можно работать с gnome-shell. В конце - выйти из системы или убить gnome-shell каким-то другим способом.
Отчёт Valgrind будет в файле vg.log в текущем каталоге.
Параметры запуска Valgrind и переменные окружения
В vg_gnome_shell.sh используется следующее.
- G_SLICE=always-malloc G_DEBUG=gc-friendly - эти переменные полезно ставить при анализе любых GTK-приложений с помощью Valgrind;
- --leak-check=full - выводить полную информацию о найденных утечках памяти.
- --show-reachable=yes - выводить информацию о блоках, которые анализируемое приложение могло бы освободить перед свои завершением (указатели на них сохранились), но не освободило.
- --fullpath-after= - выводить полный путь к файлам с исходным кодом. По умолчанию, Valgrind выдаёт только имя файла без пути. Это очень неудобно, например, если анализируемое приложение использует несколько библиотек: неясно, где искать это файл, к какому из компонентов приложения он относится. Если же поставить --fullpath-after=, отчёт будет понятнее.
- --num-callers=40 - выводить до 40 уровней в call stack. По умолчанию, Valgrind выводит не более 10-12 вызовов функций в каждом call stack. Этого часто недостаточно. 30-40 для GTK- и Qt-приложений обычно хватает.
- --log-file=vg.log - сохранять отчёт Valgrind в файле vg.log в текущем каталоге.
- --suppressions=clutter-2.0.suppressions - использовать указанный suppression file, чтобы Valgrind не выдавал соотв. ложных сообщений об ошибках. Опцию --suppressions можно использовать несколько раз - полезно, если нужно задать несколько suppression файлов.
Как показала практика, --trace-children=yes лучше не использовать, если отчёт Valgrind выводится в локальный файл. Valgrind при этом может затирать часть своих результатов, а также вести себя странно и в других отношениях. Если всё-таки хочется проверить как gnome-shell, так и порождаемые им процессы, можно попробовать выводить отчёт Valgrind не в локальный файл, а по сети (см. описание опции --log-socket, а также это пояснение).
Подробная информация о параметрах Valgrind доступна здесь: http://valgrind.org/docs/manual/manual-core.html