суббота, 1 октября 2011 г.

Новый модуль faulthandler - хороший помощник при отладке в Python

Источник: New faulthandler module in Python 3.3 helps debugging

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

Фатальные ошибки

Новый модуль faulthandler, добавленный в Python 3.3, должен помочь в данной ситуации. faulthandler предоставляет возможность дампа бэктрейса стека Python в случае фатальной проблемы наподобие ошибки сегментации, деления на 0, аварийного завершения или ошибки на шине. Включить данную функциональность в своём приложении можно вызовом faulthandler.enable(), при этом указав опцию -X faulthandler при запуске исполняемого файла Python. Ещё один вариант - это установить переменную окружения PYTHONFAULTHANDLER=1. Пример вывода:

Fatal Python error: Segmentation fault

Current thread 0x00007f7babc6b700:
  File "Lib/test/crashers/gc_inspection.py", line 29 in g
  File "Lib/test/crashers/gc_inspection.py", line 32 in <module>
Segmentation fault

Таймаут

faulthandler также позволяет дампить бэктрейс по истечению заданного таймаута. Для этого используется вызов faulthandler.dump_tracebacks_later(timeout). Эту же функцию нужно вызовать для того, чтобы перезапустить таймер. Для остановки таймера нужно вызвать функцию faulthandler.cancel_dump_tracebacks_later(). Пример вывода:

Timeout (0:01:00)!
Current thread 0x00007f987d459700:
  File "Lib/test/crashers/infinite_loop_re.py", line 20 in <module>

Опция repeat=True используется для дампа бэктрейса каждые timeout секунд, а опция exit=True применяется для немедленного завершения программы небезопасным способом, т.е. без сброса файловых буферов на диск.

Пользовательский сигнал

Если есть доступ на машину, где работает программа, можно использовать механизм faulthandler.register(signal) для установки обработчика сигналов, по которому бдует осуществляться дамп бэктрейса при получении заданного сигнала. В UNIX, например, можно использовать сигнал SIGUSR1: по команде kill -USR1 <pid> будет получен текущий бэктрейс. Эта возможность недоступна на Windows-системах. Пример вывода:

Current thread 0x00007fdc3da74700:
  File "Lib/test/crashers/infinite_loop_re.py", line 19 in <module>

Другая возможность - это явный вызов faulthandler.dump_traceback() в коде программы.

Вопросы безопасности и выходной файл

faulthandler отключён по умолчанию по соображениям безопасности, в основном потому, что он сохраняет файловый дескриптор объекта sys.stderr и пишет бэктрейсы в этот файловый дескриптор. Если sys.stderr закрыт, а дескриптор файла повторно используется, то он может быть сокетом, каналом, критическим файлом или ещё чем-нибудь другим. По умолчанию faulthandler пишет бэктрейсы в sys.stderr, но есть возможность указать другой файл. Более подробную информацию об этом можно получить в документации по faulthandler.

Стороний модуль для старых версий Python

faulthandler также поддерживается как независимый модуль для Python 2.5-3.2 на PyPI. Главное отличие между модулем в Python 3.3 и сторониим модулем - это реализация dump_tracebacks_later(): Python 3.3 использует поток и блокироку с таймаутом, тогда как независимый модуль использует SIGALRM и alarm().

Таймаут блокировки - это новоя возможность в Python 3.3. Он имеет микросекундную точность. alarm() таймер, который используется в старых версиях, обладает точностью в одну секунду, а сигнал SIGALRM может прервать текущий системный вызов, при этом системный вызов завершится с ошибкой EINTR.

Ранний успех

Новый модуль faulthandler уже помог поймать состояние гонки в нашей системе сборке - buildbot. Есть надежда, что он будет полезен также и другим программистам.

Комментариев нет:

Отправить комментарий