VEH
От: Аноним  
Дата: 20.05.09 10:04
Оценка:
Попробую в кратце описать проблему:
В приложение было принято ловить глобально все исключения путем вызова AddVectoredExceptionHandler, колбэк которого проверяет код перехваченного исключения и если это, например, EXCEPTION_ARRAY_BOUNDS_EXCEEDED или EXCEPTION_ACCESS_VIOLATION или ... создает минидамп и завершает процесс.
Также приложение использует купленные ActiveX-ы. И вот, что просходит: Некоторые ActiveX-ы обрабатывают исключения, но при этом эти исключения все-равно ловятся нашим глобальным хендлером, и в этом случае процесс завершается, что быть не должно.(т.к ActiveX ожидает это исключение и обрабатывает его). Казалась бы, что проблемму можно решить путем регистрации этого ActiveX-а в неком списке. Теперь когда исключение ловится глобальным хендлером, то проверя модуль из которого это исключение пришло, и наличия его в списке, минидамп мы создавать не будем.
Однако появляется новая проблемма — как узнать это исключение ожидаеся ActiveX-ом и он его обрабатывает, или это пропущенное исключение, и нужно завершать процесс? Какие предложения?
Re: VEH
От: Аноним  
Дата: 20.05.09 10:30
Оценка:
use SetUnhandledExceptionFilter
Re[2]: VEH
От: Аноним  
Дата: 20.05.09 10:48
Оценка:
Здравствуйте, Аноним, Вы писали:

А>use SetUnhandledExceptionFilter

Не подходит, это то, что было у нас раньше
Re: VEH
От: Андрей Россия  
Дата: 20.05.09 11:16
Оценка:
Здравствуйте, Аноним, Вы писали:

skip

мы так это делаем:

int __cdecl RecordExceptionInfo(PEXCEPTION_POINTERS pExceptPtrs)
{
  if (IsDebuggerPresent())
    return EXCEPTION_CONTINUE_SEARCH;

  // здесь пишем минидамп или выполняем какие-то другие действия
  . . .

  return EXCEPTION_EXECUTE_HANDLER;
}

int main()
{
  . . .

  __try
  {
    . . .
  }
  __except(RecordExceptionInfo(GetExceptionInformation()))
  {
  }

  . . .
}


вроде нормально работает, по крайней мере, дампы создает исправно
Re[3]: VEH
От: Аноним  
Дата: 20.05.09 12:09
Оценка:
А>>use SetUnhandledExceptionFilter
А>Не подходит, это то, что было у нас раньше
Это единственный аргумент?
Re[2]: VEH
От: Аноним  
Дата: 20.05.09 13:32
Оценка:
Здравствуйте, Андрей, Вы писали:

А>Здравствуйте, Аноним, Вы писали:


А>skip


А>мы так это делаем:


А>
А>int __cdecl RecordExceptionInfo(PEXCEPTION_POINTERS pExceptPtrs)
А>{
А>  if (IsDebuggerPresent())
А>    return EXCEPTION_CONTINUE_SEARCH;

А>  // здесь пишем минидамп или выполняем какие-то другие действия
А>  . . .

А>  return EXCEPTION_EXECUTE_HANDLER;
А>}

А>int main()
А>{
А>  . . .

А>  __try
А>  {
А>    . . .
А>  }
А>  __except(RecordExceptionInfo(GetExceptionInformation()))
А>  {
А>  }

А>  . . .
А>}
А>


А>вроде нормально работает, по крайней мере, дампы создает исправно

А если из других потоков?
Re[3]: VEH
От: Андрей Россия  
Дата: 21.05.09 03:33
Оценка:
Здравствуйте, Аноним, Вы писали:

skip

да, действительно
из других потоков работает как-то странно
Re[4]: VEH
От: Андрей Россия  
Дата: 21.05.09 04:04
Оценка:
Здравствуйте, Андрей, Вы писали:

А>skip


впрочем, и AddVectoredExceptionHandler из других потоков у меня не работает
что-то я не так делаю, видимо

а вообще предложенное решение автор рекомендует для каждого потока выполнять отдельно
код взят с codeproject.com, вроде бы (или с codeguru)

давно было, не помню уже
Re[5]: VEH
От: Андрей Россия  
Дата: 21.05.09 04:33
Оценка:
Здравствуйте, Андрей, Вы писали:

skip

да, если в каждом потоке вставить такую обработку, то все работает как надо
Re[6]: VEH
От: Аноним  
Дата: 21.05.09 12:02
Оценка:
Здравствуйте, Андрей, Вы писали:

А>Здравствуйте, Андрей, Вы писали:


А>skip


А>да, если в каждом потоке вставить такую обработку, то все работает как надо

Либо в каждом потоке встраивать __try __except, что не допустимо в больших проектах, либо вешать глобально.
Вот так:

// Исключение летит в эту функцию...
LONG NTAPI RecordExceptionInfo(PEXCEPTION_POINTERS pExceptPtrs)
{
     
    LONG exceptionCode = pExceptPtrs && pExceptPtrs->ExceptionRecord ? pExceptPtrs->ExceptionRecord->ExceptionCode : 0;
    static bool exitedProcess = false;
    if( // проверяем тип исключения
                   exceptionCode == EXCEPTION_ACCESS_VIOLATION
        || exceptionCode == EXCEPTION_ARRAY_BOUNDS_EXCEEDED
        || exceptionCode == EXCEPTION_FLT_DIVIDE_BY_ZERO
        || exceptionCode == EXCEPTION_FLT_OVERFLOW
        || exceptionCode == EXCEPTION_FLT_UNDERFLOW
        || exceptionCode == EXCEPTION_INT_DIVIDE_BY_ZERO
        || exceptionCode == EXCEPTION_INT_OVERFLOW
        || exceptionCode == EXCEPTION_IN_PAGE_ERROR
        || exceptionCode == EXCEPTION_NONCONTINUABLE_EXCEPTION
        || exceptionCode == EXCEPTION_STACK_OVERFLOW
        || exceptionCode == EXCEPTION_GUARD_PAGE
        || exceptionCode == EXCEPTION_INVALID_HANDLE
        || exceptionCode == EXCEPTION_DATATYPE_MISALIGNMENT
        || exceptionCode == EXCEPTION_BREAKPOINT
        || exceptionCode == EXCEPTION_SINGLE_STEP
        || exceptionCode == EXCEPTION_FLT_DENORMAL_OPERAND
        || exceptionCode == EXCEPTION_FLT_INEXACT_RESULT
        || exceptionCode == EXCEPTION_FLT_INVALID_OPERATION
        || exceptionCode == EXCEPTION_FLT_STACK_CHECK
        || exceptionCode == EXCEPTION_PRIV_INSTRUCTION
        || exceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION    
        || exceptionCode == EXCEPTION_INVALID_DISPOSITION
    )
    {
                 
                    
                 if(!exitedProcess)
                 {
             exitedProcess = true;
                     HANDLE hLogFile = GenerateDumpFile();
                     DumpMiniDump(hLogFile, pExceptPtrs); // здесь снемаем дамп
                     CloseHandle(hLogFile);   
                     ExitProcess(exceptionCode);
                  }
    return EXCEPTION_CONTINUE_SEARCH;
}
//Инициализируем так...
void InitializeMiniDumpCreation()
{    
    static bool testedLibrary = false;
    if(!testedLibrary)
    {
        HMODULE h = GetModuleHandle(L"kernel32.dll");
        if (!h)
        {
            //never should arrive here
            h = LoadLibrary(L"kernel32.dll");
        }
        if(h)
        {
            AddVectoredExceptionHandlerDynamic* pf  = (AddVectoredExceptionHandlerDynamic*)GetProcAddress(h, "AddVectoredExceptionHandler");
            if (pf)
            {
                pf(0,RecordExceptionInfo);
            }
        }
        testedLibrary = true;
    }
}

У меня работает нормально.
Re[4]: VEH
От: Аноним  
Дата: 21.05.09 12:13
Оценка:
Здравствуйте, Аноним, Вы писали:

А>>>use SetUnhandledExceptionFilter

А>>Не подходит, это то, что было у нас раньше
А>Это единственный аргумент?
Не подходит потому, что где-то в коде могут давить исключения и тогда они не дойдут до нас . Мы же хотим контролировать этот процесс.
К примеру, Ваш модуль, подгружемый моим приложеннием, ловит и давит АV, который сам и породил. В случае VEH, я все-равно отловлю это исключение, и несмотря на то, что Вы, где-то его давите, я снему дамп и закрою приложение.
Были еще аргументы, но к сожалению, я не разберался с этим вопросом, и решение принемал не я.
Так, что нужно работать с тем, что есть.
Re[7]: VEH
От: Андрей Россия  
Дата: 22.05.09 03:41
Оценка:
Здравствуйте, Аноним, Вы писали:

skip

К сожалению, AddVectoredExceptionHandler работает только начиная с WinXP
А у нас многие клиенты еще сидят на Win2K, поэтому приходится использовать __try / __except в каждом потоке
Зато нет проблем с тем, что ловятся лишние (не нам предназначенные) исключения
Если уж пришли в __except, значит, действительно дело плохо
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.