Здравствуйте, Беляев Алексей, Вы писали:
БА>Аннотация: БА>В статье приводится пример того, как получить управление в случае фатальной ошибки приложения, чтобы
произвести ”предсмертные” действия.
Я наверное, чего-то не понял, но почему не подходит _set_se_translator?
Здравствуйте, Беляев Алексей, Вы писали:
БА>Статья:
БА>Авторы: БА> Беляев Алексей
БА>Аннотация: БА>В статье приводится пример того, как получить управление в случае фатальной ошибки приложения, чтобы произвести ”предсмертные” действия.
Автор затронул серьезный вопрос, удовлетворительно решение которого, как мне кажется, так до сих пор и не найдено. В статье много интересной информации, но решение, предлагаемое Алексеем, к сожалению не может быть примененено при разработке приложений без принятия известной доли риска, поскольку по сути является откровенным хаком. А проблема как раз возникает именно при разработки крупных, требующих долговременной поддержки и широкого спектра совместимости приложений.
Например, первый возникающий вопрос: а будет ли приведенный код работать с низким уровнем привелегий?...
Здравствуйте, schakal, Вы писали:
S>Здравствуйте, Беляев Алексей, Вы писали:
БА>>Аннотация: БА>>В статье приводится пример того, как получить управление в случае фатальной ошибки приложения, чтобы S>произвести ”предсмертные” действия.
S>Я наверное, чего-то не понял, но почему не подходит _set_se_translator?
Ну оттранслирует он SEH в исключение C++, а необработанное C++ исключение кто хендлить будет?
Re[2]: Централизованная обработка исключений
От:
Аноним
Дата:
01.10.04 11:26
Оценка:
DL>Например, первый возникающий вопрос: а будет ли приведенный код работать с низким уровнем привелегий?...
Да, будет, единственной проблемой, которая не раскрыта в статье это корректность "хака" функции, тема довольно сложная, и путей решения очень мало. Я реально использую дизассемблирование кода функции и до тех пор пока не найду места достаточного для вставки своего кода в код системной функции, затем, копирую инструкции в новое место памяти, дабы сохранить этот код для последующего использования, и вставляю свой код непосредственно в тело системной функции. (Вообще-то так же работает библиотека detours)
Re[3]: Централизованная обработка исключений
От:
Аноним
Дата:
01.10.04 11:29
Оценка:
DL>Ну оттранслирует он SEH в исключение C++, а необработанное C++ исключение кто хендлить будет?
Об этом и статья была. У тебя в программе возникло необработанное исключение, нет разницы, С++ это исключение или нет, единственное, что тебя волнует и что ты должен сделать, узнать о том что это исключение возможно и стек его такой-то и такой-то. А уж обрабатывать его в следующих версиях или не обрабатывать, это уж тебе решать.
Здравствуйте, Аноним, Вы писали:
А>Об этом и статья была. У тебя в программе возникло необработанное исключение, нет разницы, С++ это исключение или нет, единственное, что тебя волнует и что ты должен сделать, узнать о том что это исключение возможно и стек его такой-то и такой-то. А уж обрабатывать его в следующих версиях или не обрабатывать, это уж тебе решать
Совершенно верно. Поэтому-то _set_se_translator и не подходит.
Здравствуйте, Аноним, Вы писали:
DL>>Например, первый возникающий вопрос: а будет ли приведенный код работать с низким уровнем привелегий?... А>Да, будет,
Если залогиниться в систему пользователем guest, например, и попробовать выполнить этот код, то я пратически уверен в том, что VirtualProtect вернет FALSE на просьбу дать права на запись в страницу с кодом UEF. Вы проверяли такой сценарий?
А>единственной проблемой, которая не раскрыта в статье это корректность "хака" функции, тема довольно сложная, и путей решения очень мало. Я реально использую дизассемблирование кода функции и до тех пор пока не найду места достаточного для вставки своего кода в код системной функции, затем, копирую инструкции в новое место памяти, дабы сохранить этот код для последующего использования, и вставляю свой код непосредственно в тело системной функции. (Вообще-то так же работает библиотека detours)
И это тоже проблема. Я не решился бы, например, выпускать продукт, в котором detours используется в функциональных алгоритмах. В отладочных целях — да, пожалуйста, но не для релиза.
DL>И это тоже проблема. Я не решился бы, например, выпускать продукт, в котором detours используется в функциональных алгоритмах. В отладочных целях — да, пожалуйста, но не для релиза.
и что Вы предлагаете использовать в таких случаях вместо (detours)?
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
Valery A. Boronin, RSDN Team, linkedin.com\in\boronin
R&D Mgmt & Security. AppSec & SDL. Data Protection and Systems Programming. FDE, DLP, Incident Management. Windows Filesystems and Drivers.
Я бы хотел отметить вот что
>Этот код будет работать только в семействе ОС Windows NT. Дело в том, что 2 верхних >гигабайта, где размещены системные библиотеки, в Windows 9х недоступны на запись из >пользовательского (user) режима. – прим.ред.
Редакция, как я понимаю, хотела сказать, что в отличие от NT, системные библиотеки в 9x располагаются в верхних 2 Гб и записывать туда нельзя. Но фразу можно понять так, что в отличие от 9x в NT эти верхние 2 Гб доступны... Стоило бы формулировать поточнее.
With best regards
Pavel Dvorkin
БА>Аннотация: БА>В статье приводится пример того, как получить управление в случае фатальной ошибки приложения, чтобы произвести ”предсмертные” действия.
Это великолепная статья, но все-таки не совсем на ту же тему. В ней описыватся механизм SEH и рассмаривается реализация механизма исключений C++ в MSVC 6.0 и 7.0, но ни слова не говорится о способе перехвата необработанных исключений.
Здравствуйте, Valerio, Вы писали:
DL>>И это тоже проблема. Я не решился бы, например, выпускать продукт, в котором detours используется в функциональных алгоритмах. В отладочных целях — да, пожалуйста, но не для релиза. V>и что Вы предлагаете использовать в таких случаях вместо (detours)?
Ничего. Или detours.
Мы немного уклонились от исходной темы. Да, есть приложения, в которых задачу можно решить только с помощью подобной техники, профайлер, например. Пожалуйста, берите тот же detours и используйте наздоровье. Но в документации Вам придется указать, что это приложение будет работать только под аккаунтом, обладающим такими-то и такими-то правами. Для профайлера это вполне законное требование. Но для библиотеки общего назначения, каковой, с моей точки зрения, должна являться библиотека, позволяющая приложению (всего-то навсего!) перехватывать свои же необработанные исключения, это требование становится ограничением, не позволяющим использовать такую библиотеку практически нигде.
Здравствуйте, D. Lex, Вы писали:
V>>и что Вы предлагаете использовать в таких случаях вместо (detours)? DL>Ничего. Или detours.
Чтобы ловить необработанные исключения вовсе не обязательно ставить хук на системные функции. С технической точки зрения — да, Uhnandled Filter может быть только один, но на практике кроме CRT (при инициализации) никто больше не вызывает SetUnhExcFilter, а CRT ведет себя по джентльменски — запоминает адрес предыдущего обработчика и передает управление ему после выполнения своего кода. Соответственно, если все фильтры необработанных исключений будут придерживаться такой тактики — запомнить адрес предыдущего и передать управление ему, если исключение не было обработано, — то необходимости использовать хук нет.
CRT-шный UnhandledExceptionFilter имеет обыкновение ловить C++ исключения, для которых не нашлось подходящего блока catch. Поэтому,
— если использовать подход описанный в статье, — мы будем ловить все исключения, но CRT перестанет получать управление, будет несоответствие стандарту — в случае необработанного исключения перестанет вызываться terminate
— если оставить UEF от CRT, то наш UEF будет вызываться после CRT-шного, но не будет получать C++ исключения, т.к. для них CRT вызовет terminate (показав напоследок messagebox с невнятным сообщением "program requested ...")
имхо разумный компромисс:
— использовать SetUnhandledExceptionFilter, но не обрабатывать C++ исключений (чтобы не конфликтовать с CRT)
— для необработанных C++ исключений использовать в каждом потоке set_terminate (например, сделать dll и ловить события thread_attach и thread_detach). в обработчике terminate выполнять нужную обработку.
минус этого подхода в том, что внутри terminate() нельзя добраться до текущего исключения, из-за которого разгорелся сыр-бор (или почти нельзя — покопавшись в недокументированных SEH структурах на стеке текущее исключение выудить можно для большинства случаев)
Все это имеет отношение к W2K.
На Windows 2003 появились векторные обработчики исключений, благодаря которым можно было бы попробовать решить ту же проблему более изящно — не конфликтуя с CRT и не используя hook.
Здравствуйте, Ivan, Вы писали:
I>Чтобы ловить необработанные исключения вовсе не обязательно ставить хук на системные функции. С технической точки зрения — да, Uhnandled Filter может быть только один, но на практике кроме CRT (при инициализации) никто больше не вызывает SetUnhExcFilter,
Здесь Вы категорически неправы. Как я хотел бы, чтобы так оно и было! Но увы, в винде UEF не переустанавливает разве что ленивый.
Возьмите, например, студию, создайте визардом гуевое приложение с несколькими окошками, менюшками, и т.п. На один пункт меню повесьте устанвку Вашего персонального UEF, а на кнопку, скажем — кидание исключения. Если Вы сможете добиться того, чтобы выполнить некоторую последовательность действий с этим приложением так, чтобы ваш UEF был вызван — считайте, что Вам очень сильно повезло. Потому что, к примеру, CreateWindow переустанавливает UEF несколько раз (не помню уже точно сколько, но намного больше одного), и нисколечки не собирается возвращать назад фильтр, стоявший до нее. Так что достаточно одного message box'а, чтобы Ваш фильтр пошел побоку.
I> Соответственно, если все фильтры необработанных исключений будут придерживаться такой тактики — запомнить адрес предыдущего и передать управление ему, если исключение не было обработано, — то необходимости использовать хук нет.
Ключевое слово "если". Увы, это давно уже не так.
I>имхо разумный компромисс: I>- использовать SetUnhandledExceptionFilter, но не обрабатывать C++ исключений (чтобы не конфликтовать с CRT) I>- для необработанных C++ исключений использовать в каждом потоке set_terminate (например, сделать dll и ловить события thread_attach и thread_detach). в обработчике terminate выполнять нужную обработку.
Кстати никто же не запрещает вызывать terminate() из Вашего обработчика.
I>Все это имеет отношение к W2K. I>На Windows 2003 появились векторные обработчики исключений, благодаря которым можно было бы попробовать решить ту же проблему более изящно — не конфликтуя с CRT и не используя hook.
Но нам еще очень долго придется писать код, совместимый с w2k.
Здравствуйте, D. Lex, Вы писали:
DL>Здравствуйте, Ivan, Вы писали:
DL>Здесь Вы категорически неправы. Как я хотел бы, чтобы так оно и было! Но увы, в винде UEF не переустанавливает разве что ленивый.
С какой целью ? Я не буду настаивать, что все именно так обстоит на семействе W9X, но на W2K проверял.
Если бы "все кому не лень" устанавливали UnhandledFilter, то первой перестала бы работать CRT, которая на него полагается. Я думаю, все дело в том, что время от времени в процесс загружаются различные модули dll, скомпилированные с различными версиями CRT или слинкованные с ней статически. Каждый раз, когда инициализируется CRT — вызываетя SethUnhandledExceptionFilter.
DL>Возьмите, например, студию, создайте визардом гуевое приложение с несколькими окошками, менюшками, и т.п. На один пункт меню повесьте устанвку Вашего персонального UEF, а на кнопку, скажем — кидание исключения.
На W2003 сделал тестовое приложение — внутри CreateWindow для обычного окна (Win32 Application в 7.1) не вызвался ни разу.
Если бы CreateWindow вызывал SetUnhExFilter — это сломало бы вызов terminate для необработнных C++ исключений. Это слишком очевидный и серьезный баг, чтобы иметь право на существование
DL>Кстати никто же не запрещает вызывать terminate() из Вашего обработчика.
Но это уже выглядит как попытка "немножко" переписать CRT, т.е. выполнять часть ее функций. Гораздо спокойнее не мешать ей выполнять ее функции.
DL>Но нам еще очень долго придется писать код, совместимый с w2k.
Программно можно проверять версию и на новых платформах использовать более простой и надежный код с векторным EH
Здравствуйте, Ivan, Вы писали:
> Так что достаточно одного message box'а, чтобы Ваш фильтр пошел побоку.
приведенный ниже код работает и на W2K и на W2003 — но не должен был бы, если бы CreateWindow переустанавливал UEF
Здравствуйте, Ivan, Вы писали:
I>Здравствуйте, Ivan, Вы писали:
>> Так что достаточно одного message box'а, чтобы Ваш фильтр пошел побоку. I>приведенный ниже код работает и на W2K и на W2003 — но не должен был бы, если бы CreateWindow переустанавливал UEF
Здравствуйте, Аноним, Вы писали:
А>попробуй стандартный GetOpenFileName.
попробовал на Win XP. Unhandled Exception Filter вызвался для исключения Access Violation. Могу предположить, что на некоторых платформах фильтр заменяется, так как во время вызова GetOpenFileName загружаются библиотеки (например, comctl32.dll), которые используют CRT и если типы CRT приложения и библиотек не совпадают (single, multi, static, debug), то при инициализации CRT произойдет вызов SetUnhadledExceptionFilter.
Если речь идет о фильтре CRT, то он ведет себя по товарищески , если исключение не C++, то будет вызван предыдущий фильтр, а для C++ исключений можно использовать set_terminate — см. предыдущие сообщения.
этот пример бросает C++ exception. Если раскомментировать строчку LoadLibrary, то наш фильтр не вызовется — во время загрузки mfc42.dll проинициализруется CRT и заменит фильтр, но только для C++ исключений.
Если настроить компиляцию приложения с CRT "multithreaded dll" — то при загрузке mfc71.dll инициализации CRT не будет и фильтр опять же не переустановится.