SumatraPDF давно известен как небольшой, быстрый и многофункциональный просмотрщик PDF, ePub и комиксов для Windows. Несмотря на свою популярность и стабильность, разработчик столкнулся с классической проблемой: обеспечение максимальной надёжности приложения при множестве разнородных пользовательских конфигураций и версий операционной системы. Программа, как и любой софт, могла неожиданно завершаться сбоем — и это всегда неприятно для пользователей, а значит, и для разработчика, стремящегося к совершенству. Ключевым моментом в борьбе с ошибками стал принцип: «знай свои сбои». Понимание реальных причин вылетов или зависаний невозможно без подробной информации о них.
На практике традиционная схема получения обратной связи от пользователей не срабатывала. Большинство людей не отправляют отчёты об ошибках самостоятельно, а просто перезапускают программу. Чтобы получить реальное представление о происходящем, была разработана собственная система автоматического сбора отчётов о сбоях, которая работает без участия пользователя. Для полноценного понимания проблемы важны многочисленные факторы: разная аппаратная и программная среда, особенности настроек Windows, взаимодействие с внешним ПО, а также различные пользовательские сценарии. Проверить все эти варианты вручную и гарантировать отсутствие ошибок невозможно, тем более для одного разработчика без ресурсов крупной компании.
Этот факт подчёркивает необходимость получать максимально полные и точные отчёты о сбоях напрямую с рабочих машин пользователей. В основе решения лежит интеграция в SumatraPDF сложного обработчика исключительных ситуаций и сигналов о критических ошибках. Система перехватывает сбои на уровне C++ в среде Windows, обрабатывает сигналы SIGABRT, терминальные события, а также низкоуровневые исключения процессора с помощью специализированных функций и рукописных обработчиков. Изначально реализован механизм регистрации обработчиков сигналов и исключений, в их рамках происходит искусственное создание аварийного сбоя, чья задача — активировать основной crash-обработчик. Принцип работы crash-обработчика заключается в формировании отчёта с максимально читаемым стеком вызовов, что позволяет быстро идентифицировать место возникновения ошибки.
Стек вызовов представляют в удобном виде, используя функции StackWalk64 из dbghelp.dll. Однако подобная информация — это просто адреса в памяти, а не смыслы. Для связи этих адресов с функциями, исходными файлами и конкретными строками кода необходимы специальные символы отладки (.pdb файлы).
Поскольку SumatraPDF — open source проект, было принято решение хранить символы отладки для каждой версии программы в облачном хранилище, совместимом с S3 API (Cloudflare R2). Когда происходит сбой, необходимые .pdb файлы автоматически загружаются на локальную машину, что позволяет точно преобразовать адреса стека в понятные метки функций, исходных файлов и строк. Благодаря такому подходу разработчик получает предельно информативный и удобный для анализа отчёт. Помимо стека вызовов, в отчёте содержится информация о версии операционной системы, архитектуре процессора, списке загруженных DLL и текущей конфигурации SumatraPDF.
Важной деталью является включение в программу git-хеша версии сборки. Это даёт возможность быстро соотносить отчёты с актуальным исходным кодом, формируя прямые ссылки на репозиторий GitHub — большой плюс для быстрой диагностики и исправления багов. Инфраструктура для сбора таких отчётов — это сервер на Go, размещённый на хостинге Hetzner. Он принимает crash-отчёты с клиентов через HTTP POST, сохраняет их и предоставляет простой веб-интерфейс для просмотра. Отчёты хранятся в течение недели, после чего автоматически удаляются.
Это оправдано тем, что если ошибка не повторяется, значит она исправлена, а если продолжеает появляться — свежие отчёты не дают ей скрыться. Опыт внедрения данной системы в версии SumatraPDF 1.5 показал выдающуюся эффективность. Ранее разработчик почти не получал обратной связи о сбоях, так как пользователи не спешили отправлять minidumps вручную. Новая автоматизированная система ежедневно присылала десятки отчётов, что позволяло оперативно выявлять и исправлять неисправности.
Некоторые проблемы устранялись уже после первого просмотра отчёта, другие требовали создания локальных стресс-тестов для удобства воспроизведения и отладки. Конечно, не все ошибки поддаются разрешению. Часто виновниками становятся сторонние компоненты, например, нестабильные драйверы принтеров или DLL, внедрённые другими программами. Однако благодаря глубокой диагностике разработчик сумел значительно сократить количество повторяющихся и стабильных сбоев в последующих версиях. Помимо собственного решения рассматривались альтернативные методы.
В частности, Windows предлагает использование minidump-файлов с помощью API MiniDumpWriteDumpProc. Это проще в реализации и требует меньше ресурсов на стороне клиента, однако для анализа таких дампов требуется использование отладчиков вроде WinDBG, часто с написанием скриптов и автоматизацией. Практика показала, что некоторые дампы вызывают проблемы в отладчике, что усложняет процесс. Проекты с открытым исходным кодом, такие как Google Breakpad и его преемник Crashpad, обеспечивают кроссплатформенные средства для сбора краш-репортов. Они активно используются в ведущих браузерах Chrome и Firefox.
Разработчик SumatraPDF обращал внимание на их функциональность, но предпочёл более легковесный и управляемый подход, позволяющий лучше контролировать процесс и интегрировать отчёты с исходным кодом. Также стоит отметить, что Microsoft собирает отчёты о сбоях Windows и приложений через Windows Error Reporting. Третьи лица могут получить доступ к агрегированной информации, но процедура получения таких данных сложна и закрыта для большинства разработчиков. Поэтому собственная система отчётов остаётся наилучшим вариантом для независимого и оперативного мониторинга стабильности SumatraPDF. Итогом всего проделанного является значительный прогресс по части надёжности и качества SumatraPDF.