Сейчас на форуме: UniSoft, laslo, bartolomeo (+5 невидимых) |
eXeL@B —› Программирование —› Висячая консоль и как с этим бороться |
Посл.ответ | Сообщение |
|
Создано: 04 августа 2011 18:13 · Поправил: DenCoder · Личное сообщение · #1 UPD. Под "висячей" консолью здесь имеется ввиду окно-консоль, адекватно обрабатывающее WM-сообщения, кроме как минимум WM_CLOSE, хотя процессов, к которым оно было присоединено, уже нет. UPD2. WinXP SP3 x86. csrss.exe и winsrv.dll 5.1.2600.5512. Не были использованы wowexec, ntvdm и какие-либо вообще эмуляторы Вот уже полгода мой комп мучает проклятие консольного окна. Дело в том, что иногда мне нужно быстро проверить, если доступ к тем или иным ресурсам в сети или нет, динамика пинга и на протяжении какого-то времени. Создал я простой скрипт типа Code:
Создал ярлык на него и... периодически, в 20-30% случаев, если консоль работает достаточно долго (может быть это с её буфером связано, который увеличен до 5000 строк), то её не закрыть. То ли это баг винды (WinXP SP3), то ли следствие кривой заплатки, но нажимаем на красный крестик консольного окна с пингами, cmd.exe и ping.exe завершаются, а окно висит. Да к тому же перезагрузиться после такого без резета не получается. Много раз хотел отладчиком как-нибудь подсоединиться в тот самый момент, когда окну шлётся WM_CLOSE, но чтобы при этом проявил себя как раз этот самый баг... Не представляю, как это осуществимо... И вот вчера проявилось опять то же самое. Надоело терпеть глюки винды, поэтому взял Process Explorer. Как известно, у консольных окон процесс-владелец csrss.exe, значит у него должны быть оконные процедуры для консолек. Чуть позже я узнал, что обработка сообщений консолей в winsrv.dll. К тому же через csrss.exe происходит запуск/завершение процессов. Первое, что в голову пришло - какой-то из двух процессов (cmd или ping) до конца не завершился, не отсоединил консоль - вот и результат. Process Explorer'ом навёл на csrss - полно хэндлов работающих процессов и среди них <Non-existent process>:pid... Чем хорош Process Explorer - это тем, что показывает адрес объекта в ядре(на lower pane в режиме Handles - меню View->Lower pane->Handles), для процесса - EPROCESS. Отладчиком WinDbg идём в local kernel debugging и смотрим, что по этому адресу... К сожалению, я так и научил его дружить нормально с символами, поэтому не всегда в нём могу получить описание нужной структуры. Поэтому пришлось для этого воспользоваться идой. Хотя, видно, символы не те, потому что ида из сети достаёт гораздо лучше, чем те, которые скачал когда-то(к примеру, nt!PspTerminateProcess в символах для ntoskrnl.exe нет, но ида достаёт те, в которых есть). Итак, первое, что можно увидеть - в _EPROCESS._KPROCESS._DISPATCHER_HEADER.SignalState - 1. То есть тот самый Non-existent process, всё-таки завершился, но его EPROCESS почему-то не убрался из списка. По каким причинам, гадать можно долго. Ради интереса узнаём, что это был за процесс - в _EPROCESS.ImageFileName прописано ping.exe. Вероятно, это и есть виновник - не отсоединился вовремя от консоли... Вместе с коллегой придумывали разные варианты, теоретически, как исправить ситуацию. Но отсутствие у нас в символах PspTerminateProcess заставило изменить стратегию. Повисло ведь окно, значит надо выяснить почему... В winsrv.dll, чьё апи юзает csrss.exe, наткнулся на несколько интересных функций. Среди них ConsoleClientConnectRoutine, ConsoleClientDisconnectRoutine, RemoveConsole... ConsoleWindowProc - кажется то, что надо. Нашли, что у консольного окна сначала получается USER_DATA: pUserData = GetWindowLong(hWnd, GWL_USERDATA); которая является адресом какой-то структуры. Для WM_CLOSE по смещению 0x140 в ней сначала проверяются флаги, и если один из них false, то HandleCtrlEvent в конце концов добавляет флаг 4 по смещению 0x1B8... Мы ждали более логичного конца типа DestroyWindow, а тут... Искать и перебирать все возможные обращения к этому флагу с проверкой оказалось утомительным - их было много... Эксперименты с этим флагом тоже ничего не дали... Тогда может быть pUserData + 0x140 что-нибудь даст? Провёл пару экспериментов - установка тех или иных флагов вызывал глюки отображения окна консоли, сброс возвращал окно к прежнему виду... хм... Взведение всех флагов избавило от проблемы - консоль наконец закрылась Ну на всякий случай вернул всё обратно, мало ли что. Таким образом, код завершения такого повисшего окна примерно такой: Code:
Единственное что - прозевал, нужен ли SendMessage... Дождусь очередного проявления бага - поисследую основательней... надеюсь ----- IZ.RU |
|
Создано: 04 августа 2011 18:22 · Личное сообщение · #2 Интересное исследование. Я тоже встречался с висячей консолью, но руки не доходили разобраться. Встроить бы ваш код в З.Ы. были бы все глюки винды такими безобидными... ----- PGP key |
|
Создано: 04 августа 2011 18:39 · Личное сообщение · #3 |
|
Создано: 04 августа 2011 19:06 · Личное сообщение · #4 |
|
Создано: 04 августа 2011 19:21 · Личное сообщение · #5 mysterio пишет: До кучи: http://www.nirsoft.net/utils/what_is_hang.html На nirsoft пишут: the user interface abruptly stops responding В нашём случае консоль при этом реагирует адекватно почти на все действия. Кроме того, что её закрыть нельзя. "Висячая" консоль - не в смысле, что висит процесс, связанный с ней и консоль никак не реагирует, а наоборот, процессов уже нет, а консоль живёт своей жизнью. P.S. Если б повесился csrss(здесь - в прямом, распространённом смысле), то только reset. ----- IZ.RU |
|
Создано: 04 августа 2011 19:31 · Личное сообщение · #6 |
|
Создано: 04 августа 2011 19:50 · Личное сообщение · #7 Нашёл в реестре HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SubSystems Ключ Windows Code:
Вероятно, от некоторых значений параметров в ключе зависит работа консолей. А также вижу возможность заменить winsrv.dll заменить на другую... Только, похоже, она связана с basesrv.dll, так что там же менять и её... если, конечно, это имеет смысл... ----- IZ.RU |
|
Создано: 04 августа 2011 20:55 · Поправил: reversecode · Личное сообщение · #8 а пинг именно в такой комбинации time ping goto ? а просто ping ? у меня просто ping -t google.com запускается каждый день в течении нескольких лет подряд и висит по 20 часов в день, и ничего подобно описаного не наблюдается вроде ping правда запущен постоянно с окна far, а не с самой cmd но в процессах он через cmd виден |
|
Создано: 04 августа 2011 21:20 · Личное сообщение · #9 |
|
Создано: 24 августа 2011 07:32 · Поправил: DenCoder · Личное сообщение · #10 Приём, описанный выше, хоть и грубый, но самый быстрый. Чего ещё? Вроде можно б было и закрыть темку... ан нет, упомяну две вещи: 1) Code:
Это единственно близкая к правде структура для Windows XP SP3, которой нет в W2K и которая на реактос просто перетасована(как и некоторые другие структуры)... 2) В Windows время создания тредов назначается, оказывается, от 1 января 1601 года с точностью до 100 наносекунд... И если вдруг в _ETHREAD треда, пославшего LPC, время не сходится - то это достаточная причина, чтобы повесить консоль... Хотя по мере исследований ещё штук 5 насчитал ----- IZ.RU |
eXeL@B —› Программирование —› Висячая консоль и как с этим бороться |