【发布时间】:2021-06-24 17:14:37
【问题描述】:
我有一个 Delphi Service 应用程序。 Indy TCP 服务器和许多客户端(最多 50 个),ADO 连接到 Firebird 和简单的网络交换。应用程序随机崩溃(可能在 7 天内工作,可能是 1 小时)并出现下一个事件(例如):
Имя сбойного приложения: rollcontrol.exe, версия: 1.1.20.2, метка времени: 0x60acd5f2 Имя сбойного модуля: ntdll.dll, версия: 6.3.9600.19678, метка времени: 0x5e82c0f7 Код исключения: 0xc0000005 Смещение ошибки: 0x00058def Идентификатор сбойного процесса: 0x4178
或:
Имя сбойного приложения: rollcontrol.exe, версия: 1.1.1.9, метка времени: 0x607b239c Имя сбойного модуля: msvcrt.dll, версия: 7.0.9600.16384, метка времени: 0x52158ff5 Код исключения: 0xc0000005 Смещение ошибки: 0x00009e80
应用程序中的所有作业都在匿名线程或 tcp/ip 连接线程中进行。每个线程中的所有代码都在 try 中执行,除了语句。没有内存泄漏或增加的线程数。服务线程的主要代码很简单:
procedure TRollControl_Svc.ServiceExecute(Sender: TService);
begin
while not Terminated do
try
ServiceThread.ProcessRequests(False);
ServiceThread.Sleep(100);
except
on e : exception do LogException('ServiceExecute', E);
end;
end;
如何处理此异常并防止应用崩溃?怎么可能用两行简单的代码让服务线程崩溃?
谢谢
更新:与数据库的连接示例:
function TRollControl_Svc.GetNodeIdByIP(ip: string): integer;
Var
SQLConnection : TADOConnection;
SQLQuery : TADOQuery;
Thread : TThread;
fResult : integer;
begin
fResult := 0;
try
Thread := nil;
Thread := TThread.CreateAnonymousThread(
procedure
begin
try
SQLConnection := nil;
SQLQuery := nil;
CoInitialize(nil);
SQLConnection := TADOConnection.Create(nil);
SQLConnection.ConnectionString := 'Provider=MSDASQL.1;Password=' + Psw + ';Persist Security Info=True;User ID=' + Usr + ';Data Source=' + Srv ;
SQLConnection.LoginPrompt := false;
SQLQuery := TADOQuery.Create(nil);
SQLQuery.Connection := SQLConnection;
SQLQuery.LockType := ltReadOnly;
try SQLConnection.Open; except SQLConnection.Open; end;
SQLConnection.BeginTrans;
SQLQuery.Close;
SQLQuery.SQL.Text := 'select nodes.* from nodes where nodes.ip = :ip';
SQLQuery.Parameters.ParamByName('ip').Value := ip;
try SQLQuery.Open; except SQLQuery.Open; end;
if SQLQuery.IsEmpty then exit;
fResult := SQLQuery.FieldByName('ID').AsInteger;
if SQLConnection.InTransaction then
SQLConnection.CommitTrans;
finally
TryFree(SQLQuery);
TryFree(SQLConnection);
CoUninitialize;
end;
end
);
Thread.FreeOnTerminate := false;
Thread.Start;
Thread.WaitFor;
finally
TryFree(Thread);
end;
result := fResult;
end;
【问题讨论】:
-
你在这里显示的代码很好,实际上你可以省略那段代码,最好不要实现 OnServiceexecute 因为它会做完全一样的事情。 0xc0000005 是一个外部异常,很可能在 ADO COM 层,但我们在这里看不到该代码...
-
到 ADO 的所有连接都在 TIDTCPServerExecute 过程中的 TThread.CreateAnonymousThread 等单独线程中执行。 try/except 语句中的所有代码。我不明白为什么主线程崩溃以及如何在进程终止之前捕获异常
-
如果没有 minimal reproducible example 来证明实际存在的错误,任何人都无法为您诊断。您只需要调试您的服务以在错误发生时捕获它们。在您提到的简单描述中,有很多地方可能会出错
-
我没有看到那些匿名线程的附加值,每个 TCP 连接都已经发生在它自己的线程上下文中,我猜你在某处破坏内存导致一般崩溃。如果您无法调试服务,请添加一些日志记录。
标签: delphi service crash ado indy