Освободить ресурс в случае креша?
От: adb Россия  
Дата: 11.02.22 15:07
Оценка:
Есть мультиплатформенное, мультитред приложение.

Хочется в случаях крешей освобождать один ресурс (по сути доступ к лицензии, она конечно сама отлипает, но минут через 30).
В ходе разных экспериментов выяснилось, что нет никаких проблем под линуксом или маком.
Можно использовать тот же std::set_terminate/std::signal.

Но на видне все это работает только в пределах одного треда. Создание треда я не контролирую (используем QT, Qt::ThreadPool, etc).
Пробовал SetUnhandledExceptionFilter, но срабатывает не всегда. Компиляция происходит с флагом /EHsc и менять наверно будет не совсем правильно.

__try __finally в main не дает эффекта, если упали в треде.
Плюс Qt на своих ассертах делает fast exit (заодно хоть узнал, что за зверь. По виду костыль очередной), хотя это я залечил с помощью qInstallMessageHandler. Но лечение больше похоже на костыль.

Вопрос есть ли какой-нибудь универсальный метод обработки завершения приложения при креше?
Перелопатил пол гугла, а решения так и не нашел.

Максимум, что нашел — использование dll с флагами ATTACH_THREAD для доступа к треду при его создании, но dll у меня нет, создавать ради хендлера не очень хочется.
Re: Освободить ресурс в случае креша?
От: mike_rs Россия  
Дата: 11.02.22 17:59
Оценка: 5 (2)
Здравствуйте, adb, Вы писали:

adb>Но на видне все это работает только в пределах одного треда. Создание треда я не контролирую (используем QT, Qt::ThreadPool, etc).

adb>Пробовал SetUnhandledExceptionFilter, но срабатывает не всегда. Компиляция происходит с флагом /EHsc и менять наверно будет не совсем правильно.

попробуй дополнительно VEH хендлер повесить, seh действительно не все ловит.
Re: Освободить ресурс в случае креша?
От: kov_serg Россия  
Дата: 11.02.22 18:20
Оценка:
Здравствуйте, adb, Вы писали:


adb>Вопрос есть ли какой-нибудь универсальный метод обработки завершения приложения при креше?

adb>Перелопатил пол гугла, а решения так и не нашел.
Запускаешь приложение, создёшь именовыный мутекс и пускашь процесс монитор.
Процесс ждёт этот именованный мутекс, как дождался значит процесс упал, выносишь мусор.
Re[2]: Освободить ресурс в случае креша?
От: vsb Казахстан  
Дата: 11.02.22 18:38
Оценка:
А зачем так сложно? На винде нельзя просто дождаться завершения работы конкретного процесса?
Re[2]: Освободить ресурс в случае креша?
От: VladFein США  
Дата: 11.02.22 18:57
Оценка: +1
Здравствуйте, kov_serg, Вы писали:

_>Запускаешь приложение, создёшь именовыный мутекс и пускашь процесс монитор.

_>Процесс ждёт этот именованный мутекс, как дождался значит процесс упал, выносишь мусор.

... и еще один монитор, мониторить первый монитор?

All problems in computer science can be solved by another level of indirection

...except for "too many levels of indirection"
Re: Освободить ресурс в случае креша?
От: Maniacal Россия  
Дата: 12.02.22 07:25
Оценка:
Здравствуйте, adb, Вы писали:

adb>Вопрос есть ли какой-нибудь универсальный метод обработки завершения приложения при креше?


Если крэш не по Unhadled exception, а какаой-нибудь Access Violation, то стоит попробовать функцию signal для SIGSEGV, SIGABRT и пр.(хм, надо бы и самому попробовать). А обычные exception'ы стоит отлавливать. У меня так для запуска рабочих потоков используется общая функция которая внутри try/catch(...) уже определяет какой именно рабочий поток запускали, создаёт соответствующий объект и вызывает его соответствующую функцию.
Re: Освободить ресурс в случае креша?
От: Pzz Россия https://github.com/alexpevzner
Дата: 12.02.22 08:37
Оценка: 1 (1) +1
Здравствуйте, adb, Вы писали:

adb>Вопрос есть ли какой-нибудь универсальный метод обработки завершения приложения при креше?

adb>Перелопатил пол гугла, а решения так и не нашел.

А нельзя сделать дополнительную маленькую вспомогательную програмку, которая только лицензиями и ведает? Казалось бы, она должна быть простой, и можно будет добиться ее безкрешевой работы.

А то если программа таки дожила до креша, трудно сказать, что она к этому моменту внутри себя успела поломать. Поэтому как этот креш не лови, все равно, корректную подчистку будет сложно гарантировать.
Re[3]: Освободить ресурс в случае креша?
От: Carc Россия https://vk.com/gosha_mazov
Дата: 12.02.22 08:52
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>А зачем так сложно? На винде нельзя просто дождаться завершения работы конкретного процесса?

Дождаться то можно, но как тогда узнать результат завершения процесса? Успешно или нет?

Если второй (наблюдаемый) процесс рухнет, то первый (наблюдающий) процесс все равно завершит ожидание. И как тогда первому (наблюдающему) процессу понять: второй (наблюдаемый) процесс успешно завершился и не нужно за ним ничего чистить (он сам уже всё подчистил), или второй (наблюдаемый) процесс рухнул, и соответственно за ним нужно подчистить ресурсы из первого (наблюдающего) процесса.

В принципе можно помутить с ExitCode второго (наблюдаемого) процесса… Ну, это уж на вкус и на цвет. По любому придется код менять: либо второй (наблюдаемый) процесс должен в случае успеха взводить какой-то примитив синхронизации (Mutext, Event и.т.д.), или возвращать согласованный Exit Code из при завершении…
Aml Pages Home
Re[4]: Освободить ресурс в случае креша?
От: vsb Казахстан  
Дата: 12.02.22 08:56
Оценка:
Здравствуйте, Carc, Вы писали:

vsb>>А зачем так сложно? На винде нельзя просто дождаться завершения работы конкретного процесса?

C>Дождаться то можно, но как тогда узнать результат завершения процесса? Успешно или нет?

А зачем его узнавать? Я так полагаю, лицензию освобождать в любом случае надо.

Но в целом если надо — есть же код завершения процесса. Ну в юниксе есть по крайней мере. Вроде и в винде есть. 0 — нормально, не-0 — не нормально.
Re[5]: Освободить ресурс в случае креша?
От: Carc Россия https://vk.com/gosha_mazov
Дата: 12.02.22 09:18
Оценка:
Здравствуйте, vsb, Вы писали:

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


vsb>>>А зачем так сложно? На винде нельзя просто дождаться завершения работы конкретного процесса?

C>>Дождаться то можно, но как тогда узнать результат завершения процесса? Успешно или нет?

vsb>А зачем его узнавать? Я так полагаю, лицензию освобождать в любом случае надо.

Не факт, что "освобождать в любом случае надо"…
Кто захватывает лицензию тогда? Первый процесс (наблюдатель) или второй (набдюдаемый)?

Можно не проверять, если за захват лицензии отвечает только первый процесс (наблюдатель).
Т.е. как-то так
  1. запустился первый процесс,
  2. захватил лицензию,
  3. запустил второй процесс (наблюдаемый), который делает всю полезную работу
  4. второй процесс всё сделал, и завершился
  5. первый процесс (наблюдатель) дождался завершения второго процесса (с полезной нагрузкой), и подчистил ресурсы (лицензию), и сам завершился…

Как то так… А вот если ресурс (лицензию) забирает именно второй процесс (наблюдаемый), то первому процессу (наблюдателю) нужно знать, как завершился второй (сам и корректно, и сам всё подчистил за собой) или же второй процесс рухнул (и за ним нужны подчистить ту же лицензию).

vsb>Но в целом если надо — есть же код завершения процесса. Ну в юниксе есть по крайней мере. Вроде и в винде есть. 0 — нормально, не-0 — не нормально.

Об этом я уже писал выше. Главное чтобы оба процесса (наблюдатель и наблюдаемый) друг друга взаимопонимали по этим кодам возврата…
Aml Pages Home
Отредактировано 12.02.2022 9:19 Carc . Предыдущая версия .
Re[2]: Освободить ресурс в случае креша?
От: adb Россия  
Дата: 12.02.22 12:12
Оценка: -1
Здравствуйте, kov_serg, Вы писали:
_>Запускаешь приложение, создёшь именовыный мутекс и пускашь процесс монитор.
_>Процесс ждёт этот именованный мутекс, как дождался значит процесс упал, выносишь мусор.

В другом процессе ресурс никак не освободить.
Re[2]: Освободить ресурс в случае креша?
От: adb Россия  
Дата: 12.02.22 12:24
Оценка:
Здравствуйте, Maniacal, Вы писали:

M>Если крэш не по Unhadled exception, а какаой-нибудь Access Violation, то стоит попробовать функцию signal для SIGSEGV, SIGABRT и пр.(хм, надо бы и самому попробовать). А обычные exception'ы стоит отлавливать. У меня так для запуска рабочих потоков используется общая функция которая внутри try/catch(...) уже определяет какой именно рабочий поток запускали, создаёт соответствующий объект и вызывает его соответствующую функцию.


Вот и я о том же. Всегда казалось, что это делается легко. А вот фиг. signal стоят все, как и set_terminate. И это работает под линуксами. А вот винда капризная какая-то. Обычные exception отлавливаются штатными средствами в тредах. Речь именно об Access Violation. Казалось бы SetUnhandledExceptionFilter должна с ним справится (msdn пишет, что фильтруются все треды. фильтруются SEH). Но что-то не то.
Попробую VEH, но как я понял туда будет сыпаться все, надо будет отфильтровать по флагам.

#if defined(WIN32) || defined(_WIN64)
SetUnhandledExceptionFilter(WinErrorHandler);
#endif

std::set_terminate([]() {
onAppCrashed();
});

auto f = [](int s) {
onAppCrashed();
};

std::signal(SIGINT, f);
std::signal(SIGILL, f);
std::signal(SIGFPE, f);
std::signal(SIGSEGV, f);
std::signal(SIGTERM, f);
std::signal(SIGABRT, f);
Re[2]: Освободить ресурс в случае креша?
От: adb Россия  
Дата: 12.02.22 12:46
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>А нельзя сделать дополнительную маленькую вспомогательную програмку, которая только лицензиями и ведает? Казалось бы, она должна быть простой, и можно будет добиться ее безкрешевой работы.


Pzz>А то если программа таки дожила до креша, трудно сказать, что она к этому моменту внутри себя успела поломать. Поэтому как этот креш не лови, все равно, корректную подчистку будет сложно гарантировать.


Цель, чтобы без лицензии не запускали. Если вынести лицензию в другой процесс, то что помешает запустить второй вообще без лицензии?
Более того лицензионный модуль сам по себе достаточно устойчивый. В нем есть механизм опроса сервером клиента. По дефолту выставлено время 30 минут. Если сервер в течении 30 минут не смог достучаться до клиента, то лицензия возвращается автоматически. Можно настроить сервер и выставить время в минуту, что уже вполне приемлемо. Это нормальное решение.
Но есть и чисто академический интерес. Ведь такая задача вполне распространенная и как-то должна решаться штатными средствами? У меня был шок, что оно не завелось с пол-пинка.
Re[3]: Освободить ресурс в случае креша?
От: Pzz Россия https://github.com/alexpevzner
Дата: 12.02.22 13:51
Оценка:
Здравствуйте, adb, Вы писали:

adb>Цель, чтобы без лицензии не запускали. Если вынести лицензию в другой процесс, то что помешает запустить второй вообще без лицензии?


Ну, основной процесс не должен делать ничего полезного без разрешения "лицензионного" процесса. А "лицензионный" процесс должем заниматься коммуникацией с сервером, и быстренько подчищать ее, если основной процесс куда-то пропал.

adb>Более того лицензионный модуль сам по себе достаточно устойчивый. В нем есть механизм опроса сервером клиента. По дефолту выставлено время 30 минут. Если сервер в течении 30 минут не смог достучаться до клиента, то лицензия возвращается автоматически. Можно настроить сервер и выставить время в минуту, что уже вполне приемлемо. Это нормальное решение.


Тоже вполне себе вариант.

Я бы персонализировал клиентов. Если клиент "А" пришел за лицензией, а сервер думает, что у клиента "А" уже есть лицензия, ну, надо отозвать старую и выдать новую. Или, если невозможно отозвать старую, а бы выдал новую на полчаса, а дальше продлил бы, если по старой активности не было.

adb>Но есть и чисто академический интерес. Ведь такая задача вполне распространенная и как-то должна решаться штатными средствами? У меня был шок, что оно не завелось с пол-пинка.


А как ты себе это представляешь? В "небезопасных" языках процесс может сначала наломать кучу дров, а потом уже кирдыкнуться. В тот момент, когда он уже упал, вообще ни на что нельзя рассчитывать. Например, на целостность структур данных в памяти, на целостность кучи.
Re[3]: Освободить ресурс в случае креша?
От: ononim  
Дата: 12.02.22 13:57
Оценка:
adb>Но есть и чисто академический интерес. Ведь такая задача вполне распространенная и как-то должна решаться штатными средствами? У меня был шок, что оно не завелось с пол-пинка.
Процесс после крэша — нестабилен и потому решение которое работало бы гарантированно — лишь отдельный процесс. Штатными средствами она решается именно так — drWatson/wer(windows error reporting) или как оно нынче зовется — отдельный процесс. В самом упавшем процессе может максимум быть код его запуска, и то нынче wer работает всегда.
Причины — есть ошибки при которых невозможна адекватная работа, гнапример stack overflow, разрушенный heap (тупо нельзя будет malloc-ом воспользоваться)
Как много веселых ребят, и все делают велосипед...
Re[4]: Освободить ресурс в случае креша?
От: Mystic Artifact  
Дата: 13.02.22 16:22
Оценка:
Здравствуйте, ononim, Вы писали:

adb>>Но есть и чисто академический интерес. Ведь такая задача вполне распространенная и как-то должна решаться штатными средствами? У меня был шок, что оно не завелось с пол-пинка.

O>Процесс после крэша — нестабилен и потому решение которое работало бы гарантированно — лишь отдельный процесс. Штатными средствами она решается именно так — drWatson/wer(windows error reporting) или как оно нынче зовется — отдельный процесс. В самом упавшем процессе может максимум быть код его запуска, и то нынче wer работает всегда.
Раз чисто академический интерес, то встряну:
Вот откуда эта предвзятость, по поводу выделенного? Да, по дефолту WER чего-то там собирает никому не нужное (за это конечно, MS — огромное "спасибо", кто просил?!). Но, всё таки — есть же WER API, ну, например, WerAddExcludedApplication из wer.dll (документировано всё), и SetErrorMode из kernel32.dll стоит не забывать (просто, в довесок — так или иначе оно часто ходит рядом). Почему "спасибо" им — да — оно жрёт непомерно. Есть софт, который (по требованиям) может крэшиться (потому что он сам по себе исполняет third-party код). И соответственно — это очень неприятно, когда узел и без этого нагружен, а ещё и всякие трэшовые WER чего-то там чухают непойми сколько, при этом давая на выходе ноль полезной информации... Мда. Ну это, нужно готовить. У меня просто необходимости именно дружиться с WER никогда не было. Была необходимость избавить себя от его благих намерений.
А насчёт сигналов — то, как-то нет уверенности, что они будут гарантированно выполнены вообще во всех случаях. Чисто академически — мы вызываем TerminateProcess который там не особо будет церемониться. И соответственно отсюда — почти сразу же наверное должно быть ясно, что нужен out-of-proc мониторинг (а заодно и надёжно крэш-дампы можно снять). Но, это уже вообще вот сильно зависит от типа приложения, способа их запуска. Я конечно, понимаю, что вопрос был про исключения, но вижу тут академическую проблему — херня эти сигналы, т.к. процесс может умереть и по другим поводам. Если это клиентское GUI — то скорее всего оно будет мониторить само себя (например, как делают браузеры). При чём, вот, если к примеру тупо взять хромиум — то в не-официальных билдах — есть 50% шанс на спаун процесса-монитора который будет мониторить основной процесс-монитор. Понятное дело — кода там тоже немало, и оно тоже может быть нужно. (Для ясности — для брендованных стабильных релизов — такое никогда не делается, т.е. просто один процесс-монитор без паранойи.) С другой стороны, в серверном софте — тут возможно просто координатор (спаунер) процессов за этим и следит. [Но за ним — ещё кто-то присматривает]

PS: Самый тупой случай крэшей в который я встрявал лично в жизни — это было так: софтину всегда (задолго до меня) — билдили в дебаге (потому, что C с классами в котором хрен проймешь, что происходит внутри, вроде всё правильно...). В какой-то момент креши задолбали, пришлось сделать мониторинг и всё такое, авто-перезапуск и все дела. Оно работало. И вот, с чувством полного удовлетворения, спустя какое-то время, однажды утром, оказалось, что софтина встряла в debug/assert которое показало диалог и замерло навсегда в этом положении. И мониторинг мой был ессно тупой, и ловил крэши, но крэша он не видел, потому, что программа как бы и не упала. С тех пор, откровенно говоря такое поведение ассертов жестко невзлюбил, потому, что зачем оно надо — мне лично — неясно. Даже если оно видно сразу на глазах — то там часто стэк такой что один хрен надо бежать в дебаггер. В общем, придумать несуществующих проблем — можно на ровном месте. Это не windows-специфика... это специфика говнокодинга. Страшно от такого, и от осознания, что на подобном софте держится цивилизация (а это — так).
Re[4]: Освободить ресурс в случае креша?
От: kov_serg Россия  
Дата: 13.02.22 20:16
Оценка:
Здравствуйте, Carc, Вы писали:

vsb>>А зачем так сложно? На винде нельзя просто дождаться завершения работы конкретного процесса?

C>Дождаться то можно, но как тогда узнать результат завершения процесса? Успешно или нет?

C>Если второй (наблюдаемый) процесс рухнет, то первый (наблюдающий) процесс все равно завершит ожидание.

Второй процесс как правило простой и не использует сторонние библиотеки и даже не выделяет память, просто ждёт и падать он будет крайне редко (обычно когда проблемы с железом или виндой или пользователь его пристрелит)
Мутекс освободиться сразу как только процесс рухнет, а ожидать завершения придётся несколько дольше.

C>И как тогда первому (наблюдающему) процессу понять: второй (наблюдаемый) процесс успешно завершился и не нужно за ним ничего чистить (он сам уже всё подчистил),

чистить в любом случае, если уже очищено почистить дважды
Re[5]: Освободить ресурс в случае креша?
От: ononim  
Дата: 13.02.22 20:59
Оценка:
O>>Процесс после крэша — нестабилен и потому решение которое работало бы гарантированно — лишь отдельный процесс. Штатными средствами она решается именно так — drWatson/wer(windows error reporting) или как оно нынче зовется — отдельный процесс. В самом упавшем процессе может максимум быть код его запуска, и то нынче wer работает всегда.
MA> Раз чисто академический интерес, то встряну:
Интерес у автора явно не академический. У него код падает, а он не знает почему

MA> Вот откуда эта предвзятость, по поводу выделенного?

А что вы понимаете под словом предвзятость?
Как много веселых ребят, и все делают велосипед...
Re[6]: Освободить ресурс в случае креша?
От: kov_serg Россия  
Дата: 13.02.22 21:16
Оценка:
Здравствуйте, ononim, Вы писали:

O>>>Процесс после крэша — нестабилен и потому решение которое работало бы гарантированно — лишь отдельный процесс. Штатными средствами она решается именно так — drWatson/wer(windows error reporting) или как оно нынче зовется — отдельный процесс. В самом упавшем процессе может максимум быть код его запуска, и то нынче wer работает всегда.

MA>> Раз чисто академический интерес, то встряну:
O>Интерес у автора явно не академический. У него код падает, а он не знает почему
Обычно использование сторонних библиотек позволяет получать подобные эффекты в любых количествах, особенно если их много, они сложные, многопоточные, написаны большой толпой людей в разное время еще и на C++ с UB и компилируются clang-ом
Re[6]: Освободить ресурс в случае креша?
От: Mystic Artifact  
Дата: 14.02.22 09:28
Оценка:
Здравствуйте, ononim, Вы писали:

MA>> Вот откуда эта предвзятость, по поводу выделенного?

O>А что вы понимаете под словом предвзятость?
Ниже же было расписано, что имеется ввиду по поводу выделения.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.