Проблемы с SetUnhandledExceptionFilter
От: MescalitoPeyot Украина  
Дата: 05.08.06 02:35
Оценка:
Недавно наткнулся на непонятную проблему. В небольших консольных прогах я использую маленькую dll собственного написания которая среди всего прочего ставит обработчик исключений вызывая SetUnhandledExceptionFilter (я это делал и в Dllmain, если код запроса =DLL_PROCESS_ATTACH и в отдельной экспортируемой функции вызывая её из главного модуля — на результат это не влияет). Обработчик выводил в консоль с помощью WriteConsole сообщение и завершал процесс. Однако когда я попробовал использовать свою dll в более сложной программе, где кроме главного модуля и библиотеки с обработчиком есть ещё одна dll, в которой и генерируется исключение, я обнаружил, что WriteConsole возвращается с ошибкой, а последующий вызов GetLastError даёт ERROR_INVALID_HANDLE, хотя хэндл, который я получал в dllmain или в специальной функции инициализации вызывая GetStdHandle был вполне валидным, по крайней мере до исключения.
Во вложении приведены два тестовых примера на ассемблере (код и бинарники), синтаксис fasm (sorry, на С я писать не умею)
После долгих экспериментов я выяснил, что проблему удаётся решить вызывая AllocConsole и GetStdHandle непосредственно в обработчике исключения (одного только GetStdHandle недостаточно). Однако это очень не удобно для консольных приложений.
Кто-нибудь сталкивался с пободной проблемой? Возможно, есть какие-нибудь предположения, почему исключение "портит" стандартный вывод (не просто хэндл, а весь канал), в тестовом примере я генерирую его обычным
xor eax,eax
mov [eax],eax
и проблем оно вызывать не должно. И почему портит его только исключение в дополнительной dll, но не портит исключение в главном модуле?
Re: Проблемы с SetUnhandledExceptionFilter
От: Сергей Мухин Россия  
Дата: 05.08.06 03:13
Оценка:
Здравствуйте, MescalitoPeyot, Вы писали:

MP>Недавно наткнулся на непонятную проблему. В небольших консольных прогах я использую маленькую dll собственного написания которая среди всего прочего ставит обработчик исключений вызывая SetUnhandledExceptionFilter (я это делал и в Dllmain, если код запроса =DLL_PROCESS_ATTACH и в отдельной экспортируемой функции вызывая её из главного модуля — на результат это не влияет). Обработчик выводил в консоль с помощью WriteConsole сообщение и завершал процесс. Однако когда я попробовал использовать свою dll в более сложной программе, где кроме главного модуля и библиотеки с обработчиком есть ещё одна dll, в которой и генерируется исключение, я обнаружил, что WriteConsole возвращается с ошибкой, а последующий вызов GetLastError даёт ERROR_INVALID_HANDLE, хотя хэндл, который я получал в dllmain или в специальной функции


1. все dll/exe консольные?
2. мб консоль не иниц до вызова exe, а искл происходит в dllmain
3. мб установлен другой фильтр, который снимает консоль и вызывает твой
4. у меня в SetUnhandledExceptionFilter сначала пытается вывести в консоль по WriteConsole, если неудача, то WriteFile туда же, если снова не удача, то выдается диалог.

ps
вложений не обнаружено
---
С уважением,
Сергей Мухин
Re[2]: Проблемы с SetUnhandledExceptionFilter
От: MescalitoPeyot Украина  
Дата: 05.08.06 03:34
Оценка:
СМ>1. все dll/exe консольные?
СМ>2. мб консоль не иниц до вызова exe, а искл происходит в dllmain
СМ>3. мб установлен другой фильтр, который снимает консоль и вызывает твой
СМ>4. у меня в SetUnhandledExceptionFilter сначала пытается вывести в консоль по WriteConsole, если неудача, то WriteFile туда же, если снова не удача, то выдается диалог.

1. Да. Хотя в gui наблюдается тоже самое
2. Нет. Эксперементируя я сам генерировал исключение
3. Фильтр в программе один
4. Т. е. такие траблы наблюдаются? А часто бывает так, что WriteConsole не срабатывает, а WriteFile — работает?

Блин, что-то у меня проблемы с вложением, выложу код тестовых примеров здесь (заранее прошу прощения за большой пост):

seh.dll — с обработчиком
format PE Dll
entry start

include '%FASM%\include\win32a.inc'

section '.data' data readable writeable

        nStCon  dd      0
        hOut    dd      0

        hello   db      'Hello world',0

section '.code' code readable executable

FinalSEH:
        xor     eax,eax
        push    eax
        push    nStCon
        push    11
        push    hello
        push    [hOut]
        call    [WriteConsole]
        xor     eax,eax
        inc     eax
        ret     4

outit:
        push    [hOut]
        call    [CloseHandle]
        jmp     endstart

start:
        mov     eax,[esp+8]
        test    eax,eax
        jz      outit
        dec     eax
        jz      init
        mov     eax,esp
endstart:
        ret     12

init:
        push    FinalSEH
        call    [SetUnhandledExceptionFilter]
        push    STD_OUTPUT_HANDLE
        call    [GetStdHandle]
        mov     [hOut],eax
        jmp     endstart
Init:
        ret

section '.idata' import data readable writeable

        library kernel32,'KERNEL32.DLL'

        import  kernel32,\
                WriteConsole,'WriteConsoleA',\
                AllocConsole,'AllocConsole',\
                GetStdHandle,'GetStdHandle',\
                SetUnhandledExceptionFilter,'SetUnhandledExceptionFilter',\
                ExitProcess,'ExitProcess',\
                CloseHandle,'CloseHandle'

section '.edata' export data readable

        export  'SEH.DLL',\
                Init,'Init'

section '.reloc' fixups data discardable


layer.dll — дополнительная библиотека, в которой генерируется исключение
        format PE Dll
        entry start

include '%FASM%\include\win32a.inc'

section '.code' readable executable

start:
        mov     eax,esp
        ret     12

Start:
        xor     ebx,ebx

        mov     [ebx],ebx
        push    ebx
        call    [ExitProcess]

section '.idata' import data readable writeable

        library kernel32,'KERNEL32.DLL',\
                seh,'SEH.DLL'

        import  kernel32,\
                ExitProcess,'ExitProcess'

        import  seh,\
                Init,'Init'

section '.edata' export data readable

        export  'LAYER.DLL',\
                Start,'Start'

section '.reloc' fixups data discardable


test1.asm — первый пример, главный модуль + seh.dll, WriteConsole работает
format PE at 400000h
entry start

include '%FASM%\include\win32a.inc'

section '.code' code readable executable

start:
        call    [Init]
        xor     eax,eax
        mov     [eax],eax

section '.idata' import data readable writeable

        library kernel32,'KERNEL32.DLL',\
                seh,'SEH.DLL'

        import  kernel32,\
                ExitProcess,'ExitProcess'

        import  seh,\
                Init,'Init'


test2.asm — второй пример, главный модуль + seh.dll + layer.dll в которой генерируется исключение, WriteConsole не работает
        format PE GUI 4.0 at 400000h
        entry start

include '%FASM%\include\win32a.inc'

section '.code' readable executable

start:
        xor     ebx,ebx
        call    [Init]
        call    [Start]
        push    ebx
        call    [ExitProcess]

section '.idata' import data readable writeable

        library kernel32,'KERNEL32.DLL',\
                layer,'LAYER.DLL',\
                seh,'SEH.DLL'

        import  kernel32,\
                ExitProcess,'ExitProcess'

        import  layer,\
                Start,'Start'

        import  seh,\
                Init,'Init'

Наличие вызова AllocConsole в seh.dll, размещение SetUnhandledExceptionFilter и GetStdHandle в dllmain или в специальной процедуре инициализации библиотеки, дополнительный GetStdHandle в обработчике исключений проблемы не решают — установлено опытным путём
Re[3]: Проблемы с SetUnhandledExceptionFilter
От: Сергей Мухин Россия  
Дата: 05.08.06 05:09
Оценка:
Здравствуйте, MescalitoPeyot, Вы писали:


СМ>>4. у меня в SetUnhandledExceptionFilter сначала пытается вывести в консоль по WriteConsole, если неудача, то WriteFile туда же, если снова не удача, то выдается диалог.


MP>4. Т. е. такие траблы наблюдаются? А часто бывает так, что WriteConsole не срабатывает, а WriteFile — работает?


Если вывод переназначен, я не знаю, будет ли работать WriteConsole.
---
С уважением,
Сергей Мухин
Re[3]: Проблемы с SetUnhandledExceptionFilter
От: Сергей Мухин Россия  
Дата: 05.08.06 05:32
Оценка:
см ниже

MP>section '.data' data readable writeable


MP> nStCon dd 0 ; не исп

MP> hOut dd 0

MP> hello db 'Hello world',0 ; последний байт лишний


MP>section '.code' code readable executable


MP>FinalSEH:

MP> xor eax,eax
MP> push eax
MP> push nStCon
MP> push 11
MP> push hello
MP> push [hOut]
MP> call [WriteConsole]
MP> xor eax,eax
MP> inc eax
MP> ret 4

MP>outit:

MP> push [hOut]
MP> call [CloseHandle]

handle, полученный через GetStdHandle закрывать не надо

MP> jmp endstart


MP>start:

MP> mov eax,[esp+8]
MP> test eax,eax
MP> jz outit
MP> dec eax
MP> jz init
MP> mov eax,esp
MP>endstart:
MP> ret 12

MP>init:

MP> push FinalSEH
MP> call [SetUnhandledExceptionFilter]
MP> push STD_OUTPUT_HANDLE
MP> call [GetStdHandle]
MP> mov [hOut],eax

пред. три команды я бы поставил выше на две строчки

MP> jmp endstart

MP>Init:
MP> ret


MP>Start:

MP> xor ebx,ebx

MP> mov [ebx],ebx

MP> push ebx

т.е. исключение в dllmain. система сама может ставить SEH и/или SetUnh при работе dllmain.

MP> call [ExitProcess]
---
С уважением,
Сергей Мухин
Re[3]: Проблемы с SetUnhandledExceptionFilter
От: Сергей Мухин Россия  
Дата: 05.08.06 10:32
Оценка:
Здравствуйте, MescalitoPeyot, Вы писали:

а Вы уверены, что seh.dll загружается раньше?
---
С уважением,
Сергей Мухин
Re: Проблемы с SetUnhandledExceptionFilter
От: MescalitoPeyot Украина  
Дата: 05.08.06 10:35
Оценка:
Проблема разрешилась просто: оказывается, достаточно было не создавать главный моодуль как GUI.
Re[2]: Проблемы с SetUnhandledExceptionFilter
От: Сергей Мухин Россия  
Дата: 05.08.06 11:12
Оценка:
Здравствуйте, MescalitoPeyot, Вы писали:

MP>Проблема разрешилась просто: оказывается, достаточно было не создавать главный моодуль как GUI.


о чем и было сказано в первом ответе
---
С уважением,
Сергей Мухин
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.