Аналіз ланцюжка очікування програми, що зависла, Блог по Windows

При роботі з операційною системою 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.

З появою технології обходу ланцюжка очікування, в арсеналі технічного фахівця з'явився досить дієвий метод визначення причин блокувань програми, що зависла, і розблокування підвислих процесів. Звичайно, з розуму, при вивченні інциденту варто було б проаналізувати детальніше, які саме функції потоків блокують виконання і чого саме вони чекають, але це вже зовсім інший рівень і ми не ставили собі подібної мети при написанні цієї статті. Тим не менш, тепер ми озброєні ще одним, досить простим, зрозумілим і швидким способом розблокування процесу, що завис (не відповідає). Сам собою спосіб не вимагає наявності поглиблених технічних знань, а також спеціалізованих сторонніх інструментів і спирається на штатний засіб під назвою монітор ресурсів (Resource Monitor, resmon), що є відчутною перевагою. Резюмуючи, можна сказати, що використання функції "аналіз ланцюжка очікування" програми, що зависла, досить ефективний спосіб усунення причини зависання процесу.