2010-10-07 92 views
1

我在C++中编写了一个Windows服务,需要在每天晚上的午夜重新启动,因此我对其调用exit(1)以便它可以由SCM重新启动。问题是它似乎每隔一夜就会部分启动并挂起。在事件日志中,我得到:Windows服务不会停止并重新启动

应用程序弹出 - 应用程序错误:“0x0043c145”处的指令引用“0x00000035”处的内存。内存不能被“读取”。

在打开与SQL Server 2008数据库的ODBC连接之前,它似乎失败了。我可以确认服务在重新启动之前实际退出;尽管如此,当它停止并重新启动时,我每隔一段时间就会收到一次这个错误,但是如果我反复停止并手动重新启动服务,我永远不会让它失败,如果我从一个终端端口控制进程并手动退出从那里它也永远不会失败。

如果我尝试附加一个调试器,该过程就会退出,因此我无法通过这种方式收集任何有用的信息。

我正在试图弄清楚发生了什么事情,但我不知道从哪里开始。有人有主意吗?

+0

在exit()后进程是否完全终止?先用SCM的非autorestart cfg进行测试来检查。 – pinichi 2010-10-07 06:39:43

+1

您不应该使用exit()来退出服务;有一个协议,您必须遵循才能与SCM通信并正常关机。将调试器连接到正在运行的服务不应该导致它意外退出,所以它听起来像是有些问题。该错误消息表明您的代码可能试图在某处取消引用NULL指针。 – Luke 2010-10-07 11:17:50

+0

Pinichi,今晚我会试试 – jjacksonRIAB 2010-10-09 00:29:18

回答

0

不是一个直接的答案,但如果你对Vista(和afters我认为)有一个机会,你可以试试:

"A service notifies the SCM to queue a failure action by entering the SERVICE_STOPPED state and setting SetServiceExitCode function's dwWin32ExitCode parameter to anything other than ERROR_SUCCESS."

Windows Vista introduced a new flag, FailureActionsOnNonCrashFailures, which services set if they want to be able to notify the SCM to initiate a failure action: See more in Vista services

+0

不幸的是我正在使用Windows Server 2003.应该提到那个,对不起,但是这个信息在将来会很有用。 – jjacksonRIAB 2010-10-09 00:40:50

0

设置自动生成过程的转储使用Process Dumper这个过程。您应该能够调试转储验尸以找出这种零星异常发生的原因。

添加关于数据库访问的诊断信息以查看发生异常之前已经取得了哪些进展也很有用。我想知道,如果您计划在午夜关闭服务清理任务,并在关闭完成后再次启动服务,您的退出/重新启动策略会更好。

在使用exit(1)之前关闭之后,盒子上的ODBC可能正处于一种奇怪的状态。当你尝试重新制作这个时,你说你停下来并开始它 - 在这种情况下退出模式是否相同?您能否在目标服务器上退出和重新启动之间引入一个短暂的延迟,以允许清理ODBC连接状态?

+0

我在机器上安装了进程资源管理器,并且在它挂起并将其加载到Visual Studio中之后,我将尽力获得完整转储。它在我测试完成后似乎可以工作,现在我只需要在正确的时间抓住它并查看出错的地方。 – jjacksonRIAB 2010-10-09 00:33:17

+0

退出模式总是相同。这是一个缓慢的启动过程,因为它从数据库中缓存了很多东西。它可能需要6-10秒才能开始。由于我调用exit(1),因此它应该等待一分钟才能重新启动,因为它认为出现故障。我可以延长看看会发生什么,但我不确定,因为再次如果我通过SCM手动执行操作,无论是重新启动还是启动,它都会像应该那样。 – jjacksonRIAB 2010-10-09 00:45:52