Сделайте main () "uncrashable" - PullRequest
4 голосов
/ 05 июня 2011

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

void watchMe(filename)
{
    while (true)
    {
        system(filename); //freezes as long as filename runs
        //oh, filename must be crashed. Nevermind, will be restarted            
    }
}       

int main()
{
    _beginThread(watchMe, "foo.exe");
    _beginThread(watchMe, "bar.exe");
}

Эта часть уже работает - но теперь я сталкиваюсь с проблемой, которая заключается в том, чтокогда наблюдаемое приложение - скажем, foo.exe - падает, соответствующий системный вызов останавливается, пока я не подтверждаю это красивое окно сообщения:

error msg

Это делает демона бесполезным.

То, что я думаю, может быть решением, состоит в том, чтобы сделать main () наблюдаемых программ (которые я контролирую) "нерасширяемыми", чтобы они корректно закрывались, не показывая это уродливое окно сообщения.

Примерно так:

try
{
    char *p = NULL;
    *p = 123; //nice null pointer exception
}
catch (...)
{
    cout << "Caught Exception. Terminating gracefully" << endl;
    return 0;
}

Но это не работает, так как по-прежнему выдает следующее сообщение об ошибке:

error msg

("Необработанное исключение ... Записьнарушение прав доступа ... ")

Я пробовал SetUnhandledExceptionFilter и все остальное, но безрезультатно.

Любая помощь будет принята с благодарностью.

Приветсв

Ответы [ 4 ]

5 голосов
/ 05 июня 2011

Это больше похоже на исключение SEH , чем на исключение C ++, и его нужно обрабатывать иначе, попробуйте следующий код:

__try
{
    char *p = NULL;
    *p = 123; //nice null pointer exception
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? 
             EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
    cout << "Caught Exception. Terminating gracefully" << endl;
    return 0;
}

Но это лекарство, а не лекарство, вам может повезти, если вы запустите процессы в песочнице .

0 голосов
/ 05 июня 2011

Я делал это давным-давно (в 90-х, на NT4). Я не ожидаю, что принципы изменились.

Основной подход состоит в том, что, как только вы запустили процесс, вставьте DLL, которая дублирует функциональность UnhandledExceptionFilter () из KERNEL32.DLL. Порывшись в моем старом коде, я вижу, что я пропатчил GetProcAddress, LoadLibraryA, LoadLibraryW, LoadLibraryExA, LoadLibraryExW и UnhandledExceptionFilter.

Перехват функций LoadLibrary * связан с проверкой наличия исправления для всех модулей. Пересмотренный GetProcAddress предоставил адреса исправленных версий функций, а не версий KERNEL32.DLL.

И, конечно, замена UnhandledExceptionFilter () делает то, что вы хотите. Например, запустите отладчик точно в срок, чтобы получить дамп процесса (дампы ядра реализованы в пользовательском режиме на NT и преемниках), а затем завершить процесс.

Моя реализация имела исправленные функции, реализованные с помощью __declspec (naked), и работала со всеми зарегистрированными вручную, потому что компилятор может уничтожить содержимое некоторых регистров, которые вызывающие из сборки могут не ожидать уничтожения.

Конечно, было много подробностей, но это основная схема.

0 голосов
/ 05 июня 2011

Вы можете запускать наблюдаемый процесс a-синхронно и использовать объекты ядра для связи с ним.Например, вы можете:

  1. Создать именованное событие.
  2. Запуск целевого процесса.
  3. Ожидание для созданного события
  4. В целевом процессе при возникновении сбоя откройте указанное событие и установите его .

Таким образом, ваш монитор продолжит работу, как только в наблюдаемом процессе произойдет сбой, даже если наблюдаемый процесс еще не завершен.

Кстати, вы можете контролировать внешний видПервое сообщение об ошибке с использованием drwtsn32 (или что-то еще используется в Win7), и я не уверен, но второе сообщение об ошибке может появиться только в отладочных сборках.Сборка в режиме выпуска может облегчить вам задачу, хотя, самое главное, ИМХО, это прежде всего решить причину сбоев, что будет проще в отладочных сборках.

0 голосов
/ 05 июня 2011

Вы можете изменить флаг / EHsc на / EHa в командной строке вашего компилятора (Свойства / C / C ++ / Генерация кода / Включить исключения C ++).

См. this для аналогичноговопрос по SO.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...