Привет. Мне нужно отлавливать все необработанные исключения в приложении для создания минидампа + сбора некоторой доп инфы. Я для этого использую UnhandledExceptionFilter + VectoredExceptionHandler + хук UnhandledExceptionFilter в kernel32 для обработки gsfailure. Вроде бы все исключения, кроме повреждения esp, которое описывал Clerk в http://www.wasm.ru/forum/viewtopic.php?id=29865 ловятся. Никто не знает, есть ли еще какие-нибудь фичи типа gsfailure, когда CRT прибивает процесс, не давая выполнится указанным обработчикам, или, возможно, некоторые специфические условия, при которых что-нибудь пройдет мимо ?(например в outproc-com-сервере, если исключение возникает в конструкторе требуемого объекта без векторного обработчика процесс просто дохнет, и даже хук ZwTerminateProcess не помогает)
Исключение в юзермоде не удастся словить в случае: > Регистр Esp указывает на страницу не доступную для записи. > Селектор стека являетсо невалидным, либо в совокупности с регистром Esp они ссылаются на невалидный адрес(в страницу запрещена запись). В обоих случаях при копировании аргументов в стек потока, в котором произошло исключение изза невалидности/запрета на запись в ядре возникает исключение и процесс ядро завершает, не выполняя конечную развёртку исключения в этом потоке, посылая сообщение отладчику, если он активен. Иначе перехватив точку входа в диспетчер исключений, любое исключение будет развёрнуто в нём.
Velheart Ковырялся в отладчике и вспомнил про этот топик. Есть одно замечание. Механизм по сути тотже. Вызов сервиса посредством инструкции sysenter требует чтобы регистр Edx указывал на параметры в стеке, а собственно указатель на стек в регистре Esp значения не имеет, допускается вызов сервиса хоть с нулевым значением в Esp. По возврату из сервиса на KiFastSystemCallRet ядро перезагружает регистр Esp, помещая в него значение, которое было в регистре Edx при вызове сервиса, тоесть восстанавливает стек. Если вызвать сервис с невалидным указателем в регистре Edx, то из сервиса поток вернётся, возвратив код ошибки STATUS_ACCESS_VIOLATION, но так как в Esp будет загружен невалидный указатель из Edx, а возврат исполняется на инструкцию Ret, то при выполнении этой инструкции исключение не может быть развёрнуто и ядро процесс прибьёт.
Clerk Я вот еще с такой фигней столкнулся: при некоторых исключениях в начали инициализации (я сейчас точно не помню, на по-моему даже деление на 0, хотя я думаю это не принципиально) com-сервера он молча умирал и мой UnhandledExceptionFilter не вызывался, но более того не вызывался ZwTerminateProcess, который я хукал, я подумал, что возможно процесс репортит об ошибке службе RPC, которая его запускает и видимо прибивает..Ведь процесс же не может себя уничтожить из юзермода, не вызывая ZwTerminateProcess и не производя одно из описанных тобой исключений, или я чего-то не знаю (причем c подопытным процессом все по-честному, обработка происходит в ole32.dll и rpcrt4.dll и это они чего-то делают)?
Velheart Собсвенно ядро вроде как ни при каких обстоятельствах кроме описанных не уничтожает процесс. Используй ядерный отладчик и посмотри откуда в ядре юзоется NtTerminateProcess/ZwTerminateProcess. Если KiDispatchException() - то однозначно невалидный стек. Возможная причина - после сохранения в стеке очередного значения он не был расширен, изза исчерпания его(возможных размеров). Возможно ты пропустил вызов.. Например при возникновении ошибки в загрузчике при загрузке модуля, загрузчик убивает текущий процесс, а такое может быть при наличии оконных хуков.. Посмотри вобщем под отладчиком.
Да, действительно, посмотрел сисером -- процесс прибивает служба удаленного вызова процедур, благодарю за помощь. А с багами при наличии оконных хуков я уже столкнулся, когда в тестовом приложении у меня один эксепшн ловился, а у всех остальных -- нет, из-за лингвы, как потом случайно выяснилось =)
Clerk Сорри, я наврал, процесс прибивает не RPC - служба, а DCOM, она же его и запускает, там я насколько понял такая фишка: мы в клиенте запрашиваем нужный нам интерфейс, DCOM служба запускает прцесс в котором находится наш ко-класс, и ждет на LPC порте сообщения о том что и как, и если все плохо -- убивает процесс. При этом UnhandledExceptionFilter не работает, т.к. исключение обрабатывается, но в дефолтном обработчике происходит вся эта фигня.. А вообще, мне это для работы надо.., там есть приложение с несколькими модулями-процессами, так вот нужно уметь перехватывать максимальное количество типов необработанных исключений, чтобы перед смертью сгенерировать крэш-дамп+собрать некотурую инфу о системе и хорошо представлять все случаи, когда это невозможно, и по каким причинам.
Velheart Ага, я сразу понял что это не рпк(там не юзоется сервис NtTerminateProcess, смотрел). Советую перейти в режим ядра, там как угодно сможешь любые исключения обработать, либо единственный вариант для юзермода - используй отладчик, который будет управлять основным приложением, но с единственной целью ловить исключения(ловятся все).