Snipping Tool висит на курсоре загрузки: виноват переиспользованный PID
TL;DR: Если по Win+Shift+S появляется только курсор загрузки, а процессы SnippingTool.exe копятся, помогает taskkill /f /im SnippingTool.exe. Причина в коде AppInstance из Windows App SDK: он считает переиспользованный PID живым и оставляет мьютекс захваченным.
Перестал работать хоткей для скриншотов. Каждое нажатие на секунду показывало курсор загрузки и оставляло ещё один SnippingTool.exe без окна. Когда я наконец заглянул в диспетчер задач, их там висело 19.
Решение
taskkill /f /im SnippingTool.exe
Убивать нужно все. Если по одному, то сначала прибейте ждущие, а потом тот, что держит лок, иначе ждущие проснутся и каждый откроет свой оверлей.
Что происходило
Wait Chain Traversal показал, что каждый новый экземпляр ждёт мьютекс, которым владеет один старый. Остальное прояснилось после чтения AppInstance.cpp в открытом Windows App SDK:
- Экземпляры регистрируют свои PID в общей секции памяти. При выходе свой PID никто не убирает, мёртвые записи вычищает следующий запуск.
- Единственная проверка «жив ли процесс» — удался ли
OpenProcess(SYNCHRONIZE). Если Windows уже отдала этот PID другому, постороннему процессу, мёртвая запись считается живой. - Для каждого PID из списка новый экземпляр создаёт
<app>_<pid>_Mutexс начальным владением, рассчитывая, что настоящий владелец создал его раньше. Если PID переиспользован, владельцем становится сам новый экземпляр и держит мьютекс до своего выхода. - Отменённый скриншот (Esc) оставляет процесс висеть в памяти. Если именно он держит утёкший лок, все следующие запуски ждут вечно.
У меня PID, который Snipping Tool использовал часом раньше, достался процессу Python. Через несколько часов один отменённый скриншот захватил лок, и хоткей умер.
Что пригодится при таких зависаниях
- Событие 201 в журнале
Microsoft-Windows-AppModel-Runtime/Adminфиксирует каждый запуск. Сравните со временем файлов вPictures\Screenshotsи увидите, какие запуски дали скриншот. cdb -pv -p <pid> -c "!handle 0 f Mutant; qd"из Windows SDK показывает именованные мьютексы без символов и не останавливает процесс.