Не перехватывается ошибка(как сделать устойч. приложение)
От: Armastab  
Дата: 10.08.10 18:29
Оценка:
Здравствуйте,

У меня есть серверное приложение, которое в своем процессе запускает внешние объекты (plugin), загружаемые из dll. Внещний код выполняется в одном из рабочих потоков сервера. Необходимо защитить сервер от ошибок, которые могут быть в плагинах. Самая первая идея, которая пришла мне в голову — обернуть вызов внешнего кода в блок обработки исключений try-catch или __try-except .

Я столкнулся с кодом, который убивает приложение, но не отлавливается обработкой исключений. Вот пример такого кода:
//Необходимо компилировать с ключом /EHa
#include "stdafx.h"
#include "stdarg.h"
#include "excpt.h"
#include "windows.h"

void TestParamStr(_TCHAR* lpszParam,...)
{
    va_list args;
    va_start(args,lpszParam );

    TCHAR szBuf[256];
    szBuf[0]=TCHAR(0);
    _vstprintf_s(szBuf, 256, lpszParam, args);
}

int _tmain(int argc, _TCHAR* argv[])
{
    int dwRes(0);
    __try
    {
        TestParamStr(_T("%d %d %"), 0);
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        MessageBox(NULL, _T("Exception"), _T("Exception"), MB_OK);
        dwRes = 1;
    }
    return dwRes;    
}

Т.к. в строке параметров функции _vstprintf_s количество ожидаемых параметров превышает количество реально передаваемых — вываливается ошибка, которая не отлавливается ни __try — __except, ни try-catch, программа умирает .

Вопрос:
1) Как отловить такую ошибку или защитить приложение от таких ошибок ?
2) Как лучше реализовать защиту приложения от ошибок во внешнем коде ?
Приходит в голову вариант с созданием внешнего процесса, в кот. выполнять код (так, чтобы если внешний код убивает приложение, то вываливался бы только процесс-хостер внешнего кода), и организацией межпроцессного взаимодейтсвия, но этот путь видится мне достаточно трудоемким и непростым в реализации.

Спасибо,
Armastab.
Re: Не перехватывается ошибка(как сделать устойч. приложение
От: Armastab  
Дата: 10.08.10 18:39
Оценка:
Да, забыл добавить.
Платформа на кот. это запускалось: Windows 7, компилятор MS Visual C++ 2010
Re: Не перехватывается ошибка(как сделать устойч. приложение
От: remark Россия http://www.1024cores.net/
Дата: 10.08.10 18:43
Оценка: 39 (9)
Здравствуйте, Armastab, Вы писали:

A>Вопрос:

A>1) Как отловить такую ошибку или защитить приложение от таких ошибок ?
A>2) Как лучше реализовать защиту приложения от ошибок во внешнем коде ?
A>Приходит в голову вариант с созданием внешнего процесса, в кот. выполнять код (так, чтобы если внешний код убивает приложение, то вываливался бы только процесс-хостер внешнего кода), и организацией межпроцессного взаимодейтсвия, но этот путь видится мне достаточно трудоемким и непростым в реализации.

Единственный работающий вариант — это вынесение в отдельный процесс.

По поводу перехвата ошибок. Под виндой тебе надо поставить как минимум десяток обработчиков различных ошибок — это ошибки С райнтайма, С++ рантайма и ОС. Плюс надо перехватывать TerminateProcess(), т.к. некоторые кртешные функции любят без предупреждения вызывать TerminateProcess().

Вот примерный список того, что тебе надо перехватывать:
Win32:
SetThreadStackGuarantee()
SetUnhandledExceptionFilter()
TerminateProcess()

CRT:
signal(SIGABRT);
_set_security_error_handler() // если есть
_set_invalid_parameter_handler()
_set_error_mode(_OUT_TO_STDERR);
_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);

C++RT:
std::set_terminate();
std::set_unexpected();
_set_purecall_handler();


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Не перехватывается ошибка(как сделать устойч. приложе
От: remark Россия http://www.1024cores.net/
Дата: 10.08.10 18:45
Оценка: 2 (1)
Здравствуйте, remark, Вы писали:

R>Вот примерный список того, что тебе надо перехватывать:

R>Win32:
R>SetThreadStackGuarantee()
R>SetUnhandledExceptionFilter()
R>TerminateProcess()

R>CRT:

R>signal(SIGABRT);
R>_set_security_error_handler() // если есть
R>_set_invalid_parameter_handler()
R>_set_error_mode(_OUT_TO_STDERR);
R>_set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
R>_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_DEBUG);
R>_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_DEBUG);
R>_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_DEBUG);

R>C++RT:

R>std::set_terminate();
R>std::set_unexpected();
R>_set_purecall_handler();

В данном случае это наверное был _set_invalid_parameter_handler(), который зовёт TerminateProcess(), SEHом ты его не поймаешь.


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[2]: Не перехватывается ошибка(как сделать устойч. приложе
От: Armastab  
Дата: 10.08.10 18:49
Оценка:
Здравствуйте, remark, Вы писали:

Спасибо за подробный список.

R>TerminateProcess()

А как TerminateProcess перехватить?
Re[3]: Не перехватывается ошибка(как сделать устойч. приложе
От: remark Россия http://www.1024cores.net/
Дата: 10.08.10 18:56
Оценка: 2 (1) :)
Здравствуйте, Armastab, Вы писали:

R>>TerminateProcess()

A>А как TerminateProcess перехватить?

Аааа... ну... пишешь в начало функции jmp на свой обработчик, что-то типа такого:
char* dst = (char*)TerminateProcess;
*dst = 0xe9;
*(uint32_t*)(dst+1) = (your_handler - dst - 5);

Если тебе самому не надо вызывать TerminateProcess(), то этого должно хватить.


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: А как веб-сервера от кривых cgi защищаются ?
От: Armastab  
Дата: 10.08.10 19:01
Оценка:
А вот еще интересно, как разные веб-сервера от кривых cgi-скриптов защищаются, или они их во внешних процессах запускают?
Re[2]: А как веб-сервера от кривых cgi защищаются ?
От: remark Россия http://www.1024cores.net/
Дата: 10.08.10 19:07
Оценка:
Здравствуйте, Armastab, Вы писали:

A>А вот еще интересно, как разные веб-сервера от кривых cgi-скриптов защищаются, или они их во внешних процессах запускают?


Ну собственно интерфейс CGI скриптов и подразумевает, что они запускаются в отдельных процессах.


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: А как веб-сервера от кривых cgi защищаются ?
От: Armastab  
Дата: 10.08.10 19:10
Оценка:
Здравствуйте, remark, Вы писали:

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


A>>А вот еще интересно, как разные веб-сервера от кривых cgi-скриптов защищаются, или они их во внешних процессах запускают?


R>Ну собственно интерфейс CGI скриптов и подразумевает, что они запускаются в отдельных процессах.


хм, правда ведь. Что-то я ступил...
Re[2]: Не перехватывается ошибка(как сделать устойч. приложе
От: Centaur Россия  
Дата: 10.08.10 20:51
Оценка: 2 (1)
Здравствуйте, remark, Вы писали:

R>Единственный работающий вариант — это вынесение в отдельный процесс.


+1.

R>По поводу перехвата ошибок. Под виндой тебе надо поставить как минимум десяток обработчиков различных ошибок — это ошибки С райнтайма, С++ рантайма и ОС. Плюс надо перехватывать TerminateProcess(), т.к. некоторые кртешные функции любят без предупреждения вызывать TerminateProcess().


R>Вот примерный список того, что тебе надо перехватывать:


Кроме всего прочего — никакой перехват не защитит от сошедшего с ума плагина, который возьмётся писать случайную фигню в случайные адреса. Разве что тотальная защита всех страниц памяти от записи, но тогда негде будет работать самому приложению и всем остальным плагинам.

В Windows Explorer’е как раз есть отдельный процесс для кривых shell extension’ов. И как раз недавно аналогичный механизм прикрутили к Firefox’у.
Re[4]: Не перехватывается ошибка(как сделать устойч. приложе
От: Alximik509 Россия  
Дата: 11.08.10 15:31
Оценка:
Здравствуйте, remark, Вы писали:

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


R>>>TerminateProcess()

A>>А как TerminateProcess перехватить?

R>Аааа... ну... пишешь в начало функции jmp на свой обработчик, что-то типа такого:

R>
R>char* dst = (char*)TerminateProcess;
R>*dst = 0xe9;
R>*(uint32_t*)(dst+1) = (your_handler - dst - 5);
R>

R>Если тебе самому не надо вызывать TerminateProcess(), то этого должно хватить.

R>


Сурово
Re[2]: Не перехватывается ошибка(как сделать устойч. приложе
От: P_YegreS_P Беларусь www.orienteering.bsu.by
Дата: 21.01.11 15:29
Оценка:
Здравствуйте, remark, Вы писали:

R>Вот примерный список того, что тебе надо перехватывать:


А откуда это "примерный" список?
Может есть ссылка на полный?

С уважением, Сергей Писарчик.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Re[3]: Не перехватывается ошибка(как сделать устойч. приложе
От: remark Россия http://www.1024cores.net/
Дата: 21.01.11 15:45
Оценка: 2 (1)
Здравствуйте, P_YegreS_P, Вы писали:

R>>Вот примерный список того, что тебе надо перехватывать:


P_Y>А откуда это "примерный" список?


Выстрадан

P_Y>Может есть ссылка на полный?


Нет


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.