При работе с операционной системой Windows случается ситуация, когда программа (процесс) зависает, другими словами просто перестает отвечать на запросы системы (и, соответственно, пользователя). Если программа имеет графический интерфейс, то в заголовке основного окна к имени программы добавляется статус "не отвечает", и сам интерфейс при этом зачастую перестает реагировать на какие-либо запросы оператора и визуально как бы вуалируется (затеняется).
Какие есть варианты действий в этой ситуации у пользователя? Конечно же, первое что приходит на ум, так это закрыть зависшее приложение, но в подобном решении есть один очевидный недостаток - в большинстве случаев мы теряем, характеризующиеся различной степенью важности, рабочие данные приложения. А если они достаточно критичны для пользователя? В таком случае все же стоит изыскать другой подход и, хотя бы на довольно поверхностном уровне, попытаться выяснить причину зависания процесса с целью её корректного устранения.
Почему приложения виснут? В общем случае основания для подвисания могут быть разные: как внутренние, так и внешние. К внутренним относятся ошибки в коде самого приложения, к внешним же принадлежат события, случающиеся в других процессах, от которых может каким-либо образом зависеть работоспособность нашего приложения. Для выявления подобных зависимостей разработчики предложили нам (начиная с Windows Vista) механизм под названием Обход Цепочки ожидания (Wait Chain Traversal (WCT)), который при помощи специализированных функций позволяет выявлять взаимоблокировки процессов, работающих в системе. В данной статье мы будем рассматривать инструментарий анализа цепочки ожидания зависшего приложения. В качестве подобного инструментария мы будем использовать одно из системных средств, которое носит название Монитор ресурсов.
Стоит отметить, что функционал монитора вовсе не ограничивается опциями диагностики подвисших приложений, а основным его предназначением, как раз таки является наблюдение за использованием системных ресурсов, измерение производительности системы. Но в данной заметке мы сосредоточимся на мониторе ресурсов с точки зрения использования функционала для выяснения причины зависания приложений. Дело в том, что в мониторе ресурсов как раз и реализован упоминаемый выше механизм для анализа цепочки ожидания зависшего приложения.
Запуск монитора ресурсов
Для начала, Монитор ресурсов все же следует запустить :), и сделать это можно несколькими способами. Можно запустить его через панель "Выполнить", которая вызывается нажатием комбинации клавиш Win + R или через строку поиска, затем ввести команду "resmon".
Можно при помощи комбинации Ctrl + Shift + Esc вызвать Диспетчера задач, перейти на вкладку "Быстродействие" и нажать кнопку "Монитор ресурсов".
Анализ цепочки ожидания
Сразу после запуска откроется главное окно монитора ресурсов. Нам необходимо перейти к списку запущенных на данный момент в системе процессов, и сделать это можно несколькими способами, можно активировать вкладку "Обзор", затем раскрыть область "ЦП", а можно сразу перейти на вкладку "ЦП" и развернуть область "Процессы". После развертывания интересующей нас области, мы увидим список исполняющихся в данный момент в системе процессов. Как видно на скриншоте ниже, зачастую монитор ресурсов маркирует зависшие программы (процессы) красным цветом, хотя данное правило действует не всегда. Если нажать на зависшем процессе (в нашем случае это Outlook.exe) правую кнопку мыши, то взору нашему предстанет контекстное меню:
В котором помимо основных методов работы с процессом имеется пункт "Анализ цепочки ожидания". После выбора данного пункта меню откроется отдельное диалоговое окно под названием "Анализ цепочки ожидания", в котором в древовидной форме будут перечислены процессы, окончание потоков которых ждет наше зависшее приложение.
Если внимательно проанализировать цепочки ожидания (на скриншоте, приведенном выше) и сопоставить их друг с другом, то можно сделать вывод, что в нашем случае Outlook блокирует поток 4648 процесса с идентификатором 8160 и именем iexplore.exe, который, на поверку, оказывается ни чем иным как интегрированным в систему браузером Internet Explorer. Почему у нас появилась зависимость от Internet Explorer, на данный момент понять сложно, поскольку детали инцидента давно утеряны, однако могу сделать предположение, что в почтовом клиенте Outlook было открыто какое-либо вложение, требующее функционала IE (возможно ссылающееся на внешний URL). Теперь перед нами стоит задача разблокировать подвисшее приложение (Outlook) с минимальными потерями, в идеале хотелось бы продолжить функционирование в штатном режиме без повреждения рабочих данных. Для достижения данной цели можно поступить достаточно грубо и попросту завершить блокирующий процесс iexplore.exe. Для этого, активируем чекбокс напротив записи iexplore.exe (PID: 8160) поток 4648
и нажмем кнопку Завершить процесс.
Есть и другой, менее разрушительный способ избавления от блокировки. Можно попробовать изучив проблему глубже, проанализировав все нисходящие цепочки ожидания процесса. Сначала выясняем, кто блокирует (iexplore.exe), потом спускаемся далее к виновному процессу и изучаем его цепочку ожидания и так далее. У нас появляется шанс, что следуя таким образом вниз по дереву блокировок, нам, в конечном итоге, удастся выйти на первопричину. Но вот разблокируются ли в этом случае все процессы вверх по цепочке, точно спрогнозировать нельзя. Но, вернемся к нашей проблеме.
После снятия блокирующих процессов, заблокированное приложение может не отвиснуть. Дело в том, что причиной блокировок могут являться не только внешние процессы, но и системные ресурсы, например программа может постоянно пытаться сохранить данные в файл, который в данный момент блокируется другим источником. Дописать: ЦП - раздел "Связанные дескрипторы".
Удивителен тот факт, что подобная, чрезвычайно полезная, функция не появлялась в операционной системе до версии Vista, ведь очевидно, что если бы подобный функционал был построен на использовании стандартных функций Windows API, то мы могли бы видеть его и ранее. Выходит, что функционал анализа цепочки ожидания зависшего приложения это не что иное как совершенно новый системный механизм, уже упоминавшийся нами выше и носящий название Обхода Цепочки Ожидания (Wait Chain Traversal (WCT)), позволяющий отлаживать заблокированные процессы и потоки и выявлять тупики. Цепочка ожидания - это причинно-следственная связь между событиями в системе, которая представляет собой последовательность чередующихся пар потоков и событий, каждый поток сопровождается событием, которого он ждет, а это событие, в свою очередь, сопровождается следующим потоком в цепочке, которому оно принадлежит, и так далее. Под событием в данном контексте мы подразумеваем любой тип объекта синхронизации, мьютекс, критическую секцию, COM, LPC/RPC-ответ, сообщения и прочее. Поток ждет событие начиная с момента, когда он его запрашивает и заканчивая моментом, когда он им овладевает. Блокировка находится в собственности потока с момента получения её потоком и до момента, когда он её освобождает. Понятие "владение блокировкой" подразумевает блокировку, ожидающую когда поток-владелец её освободит. Таким образом, если поток А ожидает блокировку, которой владеет поток Б, то можно смело утверждать, что поток А ждет поток Б. WCT позволяет запросить цепочку ожидания для одного или нескольких потоков путем создания сессии через использование функций WCT, таких как OpenThreadWaitChainSession
, GetThreadWaitChain
, EnumProcesses
и GetThreadWaitChain
.
sleep()
, delay()
и аналогичные функции.Выводы
С появлением технологии обхода цепочки ожидания, в арсенале технического специалиста появился довольно действенный метод определения причин блокировок зависшего приложения и разблокировки подвисших процессов. Конечно, по уму, при изучении инцидента стоило бы проанализировать более детально, какие именно функции потоков блокируют исполнение и чего именно они ждут, но это уже совершенно другой уровень и мы не ставили себе подобной цели при написании данной статьи. Тем не менее, теперь мы вооружены еще одним, достаточно простым, понятным и быстрым способом разблокировки зависшего (не отвечающего) процесса. Сам по себе способ не требует наличия углубленных технических знаний, а так же специализированных сторонних инструментов и опирается на штатное средство под названием монитор ресурсов (Resource Monitor, resmon), что является ощутимым преимуществом. Резюмируя, можно сказать, что использование функции "анализ цепочки ожидания" зависшего приложения достаточно эффективный способ устранения причины зависания процесса.