在未处理的异常情况下重启应用程序。

5

如果程序崩溃了,是否有可能自动重启程序?

类似于以下的处理流程:

  1. 抛出未处理的异常。
  2. 释放进程分配的所有资源。
  3. 重新开始并调用主函数。

我正在开发一个服务器应用程序,希望实现这种行为。如果客户端误用服务器,它可能会产生std::bac_alloc异常,此时我希望服务器能够简单地重启而不是崩溃关闭,从而避免手动启动。


1
修复服务器不是更好吗? - forsvarir
@forsvarir - 是的。但你并不总是有这样的能力。例如,我曾经在 SETI@Home 客户端的早期阶段做了类似的事情,因为它偶尔会无缘无故地死机。如果我去度假或其他什么事情,可能有一段时间我都没有注意到,这会导致我在同事中落后得很惨。不能这样! - T.E.D.
@T.E.D.:说得好,老实说,我过去曾经使用shell脚本来做类似的事情(作为安全网)。但在这种情况下,感觉可能已经有了问题的想法...但现在已经很晚了,也许我读入太多了 :) - forsvarir
@forsvarir,我曾经遇到过一个类似的情况,那是一个我没有编写代码或者拥有源代码的进程。每当它崩溃时,凌晨两点钟的电话总是让我很烦恼,所以最后我写了一个监控程序,在进程消失后自动重新启动它。虽然不是完美的解决方案,但我睡得更香了! - Mark Ransom
@forsavir:当然。但要做到100%无问题可能会很困难。 - ronag
5个回答

6
我之前在Windows中通过从另一个程序运行该程序来完成此操作,使用了win32的CreateProcess调用。然后,另一个程序会等待“被监视”的进程退出,并且如果它退出,则再次调用其CreateProcess()。您可以通过对进程的句柄执行WaitForSingleObject来等待进程退出,进程的句柄是从您的CreateProcess()调用的返回值之一。
当然,您需要编写一些代码以使监视进程及其子进程关闭自身。

被称为“看门狗”进程,这是*nix上一个相当常见的模式。如果您将应用程序编写为Windows服务,我相信您可以配置服务管理器自动重启进程。然后您需要良好的日志记录(和崩溃转储处理)来帮助诊断问题的来源。 - Mike Ellery
如果您的服务真的崩溃并停止运行,Windows 可以自动重新启动它。但是,如果它没有崩溃(例如只是挂起),Windows 就不会采取任何措施。 - Juliano
有一些方法可以使监控过程自动关闭自身及其子进程。不要就此止步 :)。 - ronag
1
@ronag - 嗯,我停下了,因为这很大程度上取决于你的监控过程是如何编写以及你想让它做什么其他事情。例如,作为一个MFC程序,你可以把那段代码放在OnExit回调函数中。作为后台进程,你可能需要编写一个特殊的“关闭”程序,来改变事件对象或其他一些东西。如果你将其编写为Windows服务,你就可以钩子到服务停止事件中去。 - T.E.D.

4
让Windows成为您的看门狗。您可以调用ChangeServiceConfig2来设置服务的故障操作。(如果您的服务器不是服务,则可能出错了。)将SERVICE_CONFIG_FAILURE_ACTIONS指定为dwInfoLevel参数,并在SERVICE_FAILURE_ACTIONS结构中,将lpsaActions设置为一个或多个SC_ACTION值的数组。您需要的类型是SC_ACTION_RESTART

3
我曾通过实现一个看门狗来做类似的事情。这个看门狗作为服务运行,并等待被监控进程的响应(称为给狗喂食)。如果由于异常而导致被监控进程崩溃,看门狗将清理并重新启动应用程序。
如果应用程序无响应(一段时间内没有响应),则看门狗将终止它,然后重新启动它。
以下是一个可能会用到的实现链接: http://www.codeproject.com/KB/security/WatchDog.aspx (注:我实现了自己的版本,但无法在此处发布。我通过快速谷歌搜索找到了这个实现,对这个特定实现没有第一手经验。)

1
如果你只是捕获异常,那么通过内部编程逻辑重新启动服务器而不完全重新启动整个程序应该是可能的。

如果您知道应用程序可能会抛出的所有异常,那么这就是正确的程序。 - Juliano
你也可以捕获任何异常。 - Christian Rau
一个 catch(...) {} 子句应该能够解决这个问题。但是静态变量可能会让人困扰。 - Cactus Golov
2
这并不能清理掉一开始导致异常的混乱。最好完全退出并从头开始。 - Mark Ransom
好的,我想一个 std::bad_alloc 错误意味着您确实处于困境中。 - Christian Rau

1

像 @T.E.D. 一样,我们在构建的应用程序中也完成了这项任务。我们的应用程序是一个 Windows 服务,因此帮助程序会停止该服务(如果它挂起则最终终止该服务),然后再次启动该服务。


1
是的,我的情况中也涉及到了一个服务。任何不怕一点Ada的人都可以在http://www.telepath.com/~dennison/Ted/SETI/SETI_Service.html上查看源代码。 - T.E.D.
太好了!我使用SETI@Home屏幕保护程序已经有一段时间了,但不幸的是还没有发现任何小绿人 :-) - Juliano

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接