Есть серверное приложение написаное на C++ и работающее в среде Windows (Linux). Это приложение может подгружать различные модули для выполнения различных задач. А вот в этих модулях может произойти AV. И как только он происходит, то все это приложение валится в хлам. Хотелось бы как-то защититься от AV, который происходит в сторонних модулях и при таком событии их выгружать. Кто-то подскажет, как правильно перехватить оный AV?
Здравствуйте, Sidorovich, Вы писали:
S>Есть серверное приложение написаное на C++ и работающее в среде Windows (Linux). Это приложение может подгружать различные модули для выполнения различных задач. А вот в этих модулях может произойти AV. И как только он происходит, то все это приложение валится в хлам. Хотелось бы как-то защититься от AV, который происходит в сторонних модулях и при таком событии их выгружать. Кто-то подскажет, как правильно перехватить оный AV?
Не имеет смысла это делать. Память у тебя разделяется между модулями и приложением. Невозможно дать какую-либо гарантию, что модуль не испортит память (или другие ресурсы) основного приложения.
A>Не имеет смысла это делать. Память у тебя разделяется между модулями и приложением. Невозможно дать какую-либо гарантию, что модуль не испортит память (или другие ресурсы) основного приложения.
Наверное можно было бы дать гарантию, если бы модули были приложенияи и общались с приложением через разделяемую память, в таком случае можно было бы ограничить их влияние на работоспособность приложения, а обработка AV и аварийное завершение ложилось бы на плечи операционной системы.
Здравствуйте, Aera, Вы писали:
A>Здравствуйте, alexeiz, Вы писали:
A>>Не имеет смысла это делать. Память у тебя разделяется между модулями и приложением. Невозможно дать какую-либо гарантию, что модуль не испортит память (или другие ресурсы) основного приложения.
A>Наверное можно было бы дать гарантию, если бы модули были приложенияи и общались с приложением через разделяемую память, в таком случае можно было бы ограничить их влияние на работоспособность приложения, а обработка AV и аварийное завершение ложилось бы на плечи операционной системы.
Дык, нужно хотя бы в обработчике сообщить (хотя бы в лог), что у нас произошла аварийная обстановка и благополучно закрыться. Вопрос не снят, но переформулирован
Здравствуйте, Sidorovich, Вы писали:
S>Есть серверное приложение написаное на C++ и работающее в среде Windows (Linux). Это приложение может подгружать различные модули для выполнения различных задач. А вот в этих модулях может произойти AV. И как только он происходит, то все это приложение валится в хлам. Хотелось бы как-то защититься от AV, который происходит в сторонних модулях и при таком событии их выгружать. Кто-то подскажет, как правильно перехватить оный AV?
Последний проект которым я занимался, это сервер под Linux, по сути своей не важно чем он занимается вопрос не в том. Дело в том что если у вас винда то любой VA можно перехватить по catch(...), но это совсем не годится для линукса, так как в этом случае апликухе будет послан сигнал как то например 11(SIGSEGV), который и сигнализарует о такой поганой ситуации. Как однозначно лечить такие моменты в рантайме я не знаю, однозначно нужно делать так что такие моменты возникали как можно реже, но если они возникли то нужно как можно быстрее уведомить разработчика. Поэтому у меня на самом старте регистрируется обработчик сигналов и по приходу которых посылается email с описанием проблемы, конечно это можно положить и в лог. А на сколько оперативно вы отреагируете — это уже административный вопрос.
Здравствуйте, Sidorovich, Вы писали:
S>Есть серверное приложение написаное на C++ и работающее в среде Windows (Linux). Это приложение может подгружать различные модули для выполнения различных задач. А вот в этих модулях может произойти AV. И как только он происходит, то все это приложение валится в хлам. Хотелось бы как-то защититься от AV, который происходит в сторонних модулях и при таком событии их выгружать. Кто-то подскажет, как правильно перехватить оный AV?
Здравствуйте, alexeiz, Вы писали:
A>Здравствуйте, Sidorovich, Вы писали:
S>>Есть серверное приложение написаное на C++ и работающее в среде Windows (Linux). Это приложение может подгружать различные модули для выполнения различных задач. А вот в этих модулях может произойти AV. И как только он происходит, то все это приложение валится в хлам. Хотелось бы как-то защититься от AV, который происходит в сторонних модулях и при таком событии их выгружать. Кто-то подскажет, как правильно перехватить оный AV?
A>Не имеет смысла это делать. Память у тебя разделяется между модулями и приложением. Невозможно дать какую-либо гарантию, что модуль не испортит память (или другие ресурсы) основного приложения.
Достаточно часто AV происходит при записи/чтении либо нулевого указателя, либо "своего" удалённого указателя, либо вокруг "своего" буфера. Поэтому достаточно часто подавление AV даёт положительные результаты, т.к. накрывается только один поток, а не все, и не все теряют свои данные + сервер остаётся доступен.
сторонних модулях и при таком событии их выгружать. Кто-то подскажет, как правильно перехватить оный AV?
_>Последний проект которым я занимался, это сервер под Linux, по сути своей не важно чем он занимается вопрос не в том. Дело в том что если у вас винда то любой VA можно перехватить по catch(...), но это совсем не годится для линукса, так как в этом случае апликухе будет послан сигнал как то например 11(SIGSEGV), который и
Я тоже так думал. Но ошибся. catch (...) AV не перехватил .
Здравствуйте, Sidorovich, Вы писали:
S> Дык, нужно хотя бы в обработчике сообщить (хотя бы в лог), что у нас произошла аварийная обстановка и благополучно закрыться. Вопрос не снят, но переформулирован
Для виндоса — см. SetUnhandledExceptionFilter. UnhandledExceptionFilter ловит необработанные исключения в любом треде.
Кросплатформенно — видимо signal с SIGSEGV, но сам не пользовал
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Здравствуйте, remark, Вы писали:
S>>>Есть серверное приложение написаное на C++ и работающее в среде Windows (Linux). Это приложение может подгружать различные модули для выполнения различных задач. А вот в этих модулях может произойти AV. И как только он происходит, то все это приложение валится в хлам. Хотелось бы как-то защититься от AV, который происходит в сторонних модулях и при таком событии их выгружать. Кто-то подскажет, как правильно перехватить оный AV?
R>Достаточно часто AV происходит при записи/чтении либо нулевого указателя, либо "своего" удалённого указателя, либо вокруг "своего" буфера. Поэтому достаточно часто подавление AV даёт положительные результаты, т.к. накрывается только один поток, а не все, и не все теряют свои данные + сервер остаётся доступен.
R>Такая ситуация достаточно редка: R>
R>int* p = rand();
R>*p = 0;
R>
Это, как раз, очень частая ситуация:
struct xxx
{
int * p;
};
xxx a;
if (a. p)
* a. p = 0; // не выглядит, как rand, однако, таковой явдяетсяelse
throw ("Блин, память не выделена!");
Здравствуйте, <Аноним>, Вы писали:
А>Единственный надежный способ уберечься от AV в других модулях — это запуск в другом процессе. А>Иначе есть верный шанс, что будет порушена память у вас.
Ну, почему? Если произошел AV по чтению, то вообще еще ничего не порушено и можно со спокойной совестью сказать пользователю, что мол извините, лавочка закрывается в связи с некорректным поведением одного из компонентов, и нормально безболезненно завершить приложение (при этом не вызывать больше функций из того нехорошего модуля, чтобы не усугублять). По крайней мере текущие данные не будут безвозвратно потеряны.
Здравствуйте, trophim, Вы писали:
T>Здравствуйте, <Аноним>, Вы писали:
А>>Единственный надежный способ уберечься от AV в других модулях — это запуск в другом процессе. А>>Иначе есть верный шанс, что будет порушена память у вас.
T>Ну, почему? Если произошел AV по чтению, то вообще еще ничего не порушено
Допустим происходит банальный buffer overflow, переписывается стек (и адрес возврата на нём), а при попытке возврата происходит AV по чтению. Что ты тогда будешь делать?
Ага. Сервер банковских транзакций. Клиент снимает 10000$. Валится AV. Гасится, сумма снимается со счета клиента, но не выдается. А потом изза нарушенной логики выдается другому клиенту который снимает 100$. Зато сервер работает
Любые исключения надо не гасить, а писать в лог, дампить себя, и, если важна работа сервера — рестартится.
Но лучше даже не рестартится при возмоджности тк это может быть признаком "ощупывания" хакером сервера на предмет наличия buffer-overflow, в таком случае хакер уже все нащупал и следующим ходом снимет себе 10000$
Здравствуйте, Sidorovich, Вы писали:
S>Есть серверное приложение написаное на C++ и работающее в среде Windows (Linux). Это приложение может подгружать различные модули для выполнения различных задач. А вот в этих модулях может произойти AV. И как только он происходит, то все это приложение валится в хлам. Хотелось бы как-то защититься от AV, который происходит в сторонних модулях и при таком событии их выгружать. Кто-то подскажет, как правильно перехватить оный AV?
Ситуация очень мерзкая и ничем не отличается от того случая, когда AV выскакивает в твоем собственном исполнимом модуле. Можно пытаться перехватывать сигналы Linux-а (кажется, SIGSEGV, 11), в Win должен спасти SEH и SetUnhandledExceptionFilter или как его там.
Но красиво и хорошо сделать не получится. Нужна либо стандартная связка fork/IPC, либо дополнительная программка-Watchdog, которая снова запустит упавшее приложение и передаст ему аргументы ком. строки, по которым оно сможет восстановить свое состояние на момент, предшествующий падению. (Для этого надо, конченно, это состояние периодически сохранять.)
Тот, кто желает, но не делает, распространяет чуму.
Здравствуйте, apple-antonovka, Вы писали:
AA>Ага. Сервер банковских транзакций. Клиент снимает 10000$. Валится AV. Гасится, сумма снимается со счета клиента, но не выдается. А потом изза нарушенной логики выдается другому клиенту который снимает 100$. Зато сервер работает AA>Любые исключения надо не гасить, а писать в лог, дампить себя, и, если важна работа сервера — рестартится. AA>Но лучше даже не рестартится при возмоджности тк это может быть признаком "ощупывания" хакером сервера на предмет наличия buffer-overflow, в таком случае хакер уже все нащупал и следующим ходом снимет себе 10000$
А вот плохой пример — транзакция на то и нужна, что при AV хоть прога и закроется с сохранением состояния, но транзакция будет отменена, ведь внутри нее произошло исключение. На то она и транзакция. Так что давайте другой пример.
А вообще я говорил про "обычные" (не надо меня просить определить категорию обычности) программы, типа Ворда, который даже при падении сохраняет все же текущее состояние.
Здравствуйте, Sidorovich, Вы писали:
S>только он происходит, то все это приложение валится в хлам. Хотелось бы как-то защититься от AV, который происходит в сторонних модулях и при таком событии их выгружать. Кто-то подскажет, как правильно перехватить оный AV?
Есть токо идея как это можно организовать, остальное весит на возвожностях АПИ винды.
Значит перед загрузкой "недоброкачественных" библиотек создавать для них специальный хип и загружать их в отдельные потоки. При запуске таких потоков, устанавливать для них этот хип. Таким образом, если библиотека падает — перехватывать AV -> закрывать поток -> закрывать этот хип. Единственный недостаток — придётся также выгружать/перезагружать все остальные "надоброкачественные" библиотеки, которые ещё "не успели" упасть и кушали этот хип..
Что-то вот такое, осталось только реализовать
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
T>А вот плохой пример — транзакция на то и нужна, что при AV хоть прога и закроется с сохранением состояния, но транзакция будет отменена, ведь внутри нее произошло исключение. На то она и транзакция. Так что давайте другой пример.
Транзакция ведь кем-то обслуживается, правда?
T>А вообще я говорил про "обычные" (не надо меня просить определить категорию обычности) программы, типа Ворда, который даже при падении сохраняет все же текущее состояние.
Для Врода сохранить некорректные данные лучше чем ничего не сохранить.
Для сервера обычно лучше ничего не делать если чтото "не так".
Даже ворд перезапускается после любого AV, а ведь мог бы погасить, сказать юзеру что-то мол "я тут сохранил твой текст, малоли" и дальше работать.
Здравствуйте, apple-antonovka, Вы писали:
T>>А вот плохой пример — транзакция на то и нужна, что при AV хоть прога и закроется с сохранением состояния, но транзакция будет отменена, ведь внутри нее произошло исключение. На то она и транзакция. Так что давайте другой пример. AA>Транзакция ведь кем-то обслуживается, правда?
Ну, правда. Только если исключения возникают, то транзакция и не начинается вовсе. Даже если исключения высыпаются в коде который занимается фиксированием того факта, что началась транзакция, то ничего критичного не произойдет — эта самая транзакция вообще не начнется, ибо валятся AV. Т.е. часть программы, занимающаяся самим процессом проведения транзакций должна быть к исключениям особенно чувствительна: чуть что не так — сразу выключаем систему.
Т.о. я утверждаю что транзакция либо вся заканчивается и внутри нее не было вообще никаких AV, либо вся она отменяется.
Примерно вот так. Что некорректно сформулировал?
T>>А вообще я говорил про "обычные" (не надо меня просить определить категорию обычности) программы, типа Ворда, который даже при падении сохраняет все же текущее состояние. AA>Для Врода сохранить некорректные данные лучше чем ничего не сохранить. AA>Для сервера обычно лучше ничего не делать если чтото "не так". AA>Даже ворд перезапускается после любого AV, а ведь мог бы погасить, сказать юзеру что-то мол "я тут сохранил твой текст, малоли" и дальше работать.
Дальше работать это совершенно не приемлимо в любом случае — сервер это или Ворд. Завершение работы в любом случае. А уж восстановится программа потом или нет...