Blog. Just Blog

Перезапуск приложения в случае его аварийного завершения

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Образ мышления: Assembler | Автор: ManHunter
Перезапуск приложения в случае его аварийного завершения
Перезапуск приложения в случае его аварийного завершения

Небольшое дополнение к статье про обработку критических ошибок. Обработать возникшую ошибку, сохранить в лог состояние регистров на момент падения, уведомить пользователя о произошедшем - это хорошо и правильно. Но в Windows есть еще один интересный механизм обработки критических ошибок. Речь идет об автоматическом перезапуске приложения в случае возникновения нештатной ситуации типа необрабатываемого исключения или безответного зависания.

Делается это при помощи штатной функции RegisterApplicationRestart, которая доступна для использования, начиная с Windows Vista. Первым параметром указывается юникодная строка, которая будет передана в качестве параметра при перезапуске, причем юникодной она должна быть независимо от кодировки самого приложения. Вторым параметром можно настроить ситуации, при которых перезапуск выполняться не будет. Например, можно оставить только возможность перезапуска при зависании, а всякие деления на ноль, запись в запрещенные участки памяти и т.п. обрабатывать уже известными нам способами. Через параметры командной строки можно уведомлять приложение, что оно было перезапущено после аварийного завершения, тем самым давая возможность как-то реагировать на произошедшее. Например:
  1. ; Параметры командной строки на каждый из случаев возможного падения
  2. szCmd1  du '/error:MarlesonOne',0
  3. szCmd2  du '/error:MarlesonTwo',0
  4.         ...
  5.         ...
  6.         ; Первая часть Марлезонского балета
  7.         invoke  RegisterApplicationRestart,szCmd1,0
  8.         ...
  9.         ; Какие-то действия с возможностью падения
  10.         ...
  11.         ; Вторая часть Марлезонского балета
  12.         invoke  RegisterApplicationRestart,szCmd2,0
  13.         ...
  14.         ; Еще немного действий с возможностью падения
  15.         ...
  16.         ; Все самое страшное уже позади
  17.         invoke  UnregisterApplicationRestart
Здесь по мере выполнения каких-либо действий, которые потенциально могут привести к падению приложения, устанавливается тот или иной параметр командной строки, который будет передан приложению в случае аварийного перезапуска. При каждом вызове функции RegisterApplicationRestart предыдущее значение командной строки заменяется на новое. В конце критического участка, если перезапуск больше не требуется, вызывается функция отмены UnregisterApplicationRestart.

Важное замечание. Возможность перезапуска у приложения появляется только в том случае, если оно отработало уже не менее 60 секунд. Это сделано специально, чтобы не нагружать систему постоянными перезапусками кривого приложения, которое валится еще при старте.

Перезапуск приложения при зависании
Перезапуск приложения при зависании

В случае безответного зависания приложения и при выполнении условия 60 секунд, приложение не перезапускается автоматически, а просто в меню выбора возможных действий пользователя добавляется еще один пункт "Перезапустить программу".

Командная строка - не единственный способ передать программе информацию о перезапуске. С помощью вызова RegisterApplicationRecoveryCallback можно задать callback-функцию, которая получит управление перед тем, как приложение перезапустится. Одним из параметров при установке callback-функции является время, отводимое на восстановление, по умолчанию это 5 секунд, но не более 5 минут. Во время процесса восстановления приложение должно вызывать функцию ApplicationRecoveryInProgress в течение указанного интервала, чтобы сигнализировать системе, что программе еще требуется время. Когда все восстановительные операции выполнены, приложение должно вызвать функцию ApplicationRecoveryFinished, чтобы система зря не тратила время на ожидание.
  1.         ; Зарегистрировать callback-функцию для перезапуска
  2.         ; и отвести на восстановление 60 секунд
  3.         invoke  RegisterApplicationRecoveryCallback,\
  4.                 ApplicationRecoveryCallback,NULL,60000,NULL
  5.         ...
  6.         ...
  7. ;--------------------------------------------------------------------
  8. ; Callback-функция, которая вызывается при перезапуске программы
  9. ;--------------------------------------------------------------------
  10. proc ApplicationRecoveryCallback pvParameter:DWORD
  11.         ; Сигнализировать системе, что процесс восстановления запущен
  12.         invoke  ApplicationRecoveryInProgress,tmp
  13.         or      eax,eax
  14.         jz      @f
  15.         ; Возникла ошибка, прервать восстановление
  16.         invoke  ApplicationRecoveryFinished,FALSE
  17.         jmp     .loc_ret
  18. @@:
  19.         ; Восстановление отменено пользователем
  20.         cmp     [tmp],TRUE
  21.         je      .loc_ret
  22.  
  23.         ; ... запустить процесс восстановления ...
  24.  
  25.         ; Сигнализировать системе, что процесс восстановления окончен
  26.         invoke  ApplicationRecoveryFinished,TRUE
  27. .loc_ret:
  28.         ret
  29. endp
В приложении пример программы с исходным текстом, которая имитирует различные необрабатываемые ошибки и зависание, но дает возможность автоматического перезапуска. Перед запуском она дополнительно выводит параметры командной строки.

Пример программы с исходным текстом (FASM)Пример программы с исходным текстом (FASM)

Auto.Restart.Demo.zip (5,845 bytes)


Поделиться ссылкой ВКонтакте
Просмотров: 1874 | Комментариев: 5

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (15.07.2021 в 10:31):
Бесполезной ее делает бездумное использование. А так это отличный инструмент для обработки ошибок с возможностью получать репорты от пользователей.
Малькодор (15.07.2021 в 08:32):
Интересная штука, но
> а просто в меню выбора возможных действий пользователя добавляется еще один пункт "Перезапустить программу"
делает фичу практически бесполезной на мой взгляд
Petya (07.04.2021 в 17:19):
А, не заметил. Тогда может пригодиться.
ManHunter (07.04.2021 в 17:15):
Как минимум через SEH/VEH не обработать безответное зависание.
Petya (07.04.2021 в 17:12):
ЦитатаRegisterApplicationRecoveryCallback

А есть принципиальные отличия от оборачивания всего в SEH/VEH?

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.0056 сек.) / Память: 4.5 Mb
Наверх