应用程序冻结时出现奇怪的调用堆栈
我显然在我的一个应用程序中遇到了死锁问题,并开始调查EurekaLog堆栈跟踪。 这是最近的一个:
Call Stack Information: -------------------------------------------------------------------------------------------------------------------------------------- |Address |Module |Unit |Class |Procedure/Method |Line | -------------------------------------------------------------------------------------------------------------------------------------- |*Exception Thread: ID=14208; Priority=0; Class=; [Main] | |------------------------------------------------------------------------------------------------------------------------------------| |7C82860C|ntdll.dll | | |KiFastSystemCall | | |7C827D27|ntdll.dll | | |ZwWaitForSingleObject | | |77E61C96|kernel32.dll | | |WaitForSingleObjectEx | | |77E61C88|kernel32.dll | | |WaitForSingleObject | | |77E61C7B|kernel32.dll | | |WaitForSingleObject | | |004151C4|MyApp.exe |sysutils.pas |TMultiReadExclusiveWriteSynchronizer|WaitForWriteSignal |16740[1] | |004151BC|MyApp.exe |sysutils.pas |TMultiReadExclusiveWriteSynchronizer|WaitForWriteSignal |16740[1] | |0041522C|MyApp.exe |sysutils.pas |TMultiReadExclusiveWriteSynchronizer|BeginWrite |16818[57] | |004323FB|MyApp.exe |Classes.pas |TDataModule |Create |11357[1] | |004323C0|MyApp.exe |Classes.pas |TDataModule |Create |11356[0] | |007D744D|MyApp.exe |uRORemoteDataModule.pas |TRORemoteDataModule |Create |163[1] | |007D7434|MyApp.exe |uRORemoteDataModule.pas |TRORemoteDataModule |Create |162[0] | |007DBFAB|MyApp.exe |Sentrol_Impl.pas | |Create_Sentrol |85[1] | |00646952|MyApp.exe |uROServer.pas |TROInvoker |CustomHandleMessage |726[11] | |00407BFA|MyApp.exe |system.pas |TInterfacedObject |_AddRef |17972[1] | |00404934|MyApp.exe |system.pas |TObject |GetInterface |9003[8] | |00407B1C|MyApp.exe |system.pas | |_IntfClear |17817[1] | |00404966|MyApp.exe |system.pas |TObject |GetInterface |9009[14] | |004048E8|MyApp.exe |system.pas |TObject |GetInterface |8995[0] | |00407BD7|MyApp.exe |system.pas |TInterfacedObject |QueryInterface |17964[1] | |77E61680|kernel32.dll | | |InterlockedDecrement | | |00407C10|MyApp.exe |system.pas |TInterfacedObject |_Release |17977[1] | |00407B2C|MyApp.exe |system.pas | |_IntfClear |17824[8] | |004067DF|MyApp.exe |system.pas | |_FinalizeArray |15233[100]| |00407B1C|MyApp.exe |system.pas | |_IntfClear |17817[1] | |00646577|MyApp.exe |uROServer.pas |TROClassFactoryList |FindClassFactoryByInterfaceName|619[17] | |77E6166C|kernel32.dll | | |InterlockedIncrement | | |00407BFA|MyApp.exe |system.pas |TInterfacedObject |_AddRef |17972[1] | |00646B72|MyApp.exe |uROServer.pas |TROInvoker |HandleMessage |758[1] | |006460C5|MyApp.exe |uROServer.pas | |MainProcessMessage |512[98] | |00645BAC|MyApp.exe |uROServer.pas | |MainProcessMessage |414[0] | |00647184|MyApp.exe |uROServer.pas |TROMessageDispatcher |ProcessMessage |929[2] | |00647130|MyApp.exe |uROServer.pas |TROMessageDispatcher |ProcessMessage |927[0] | |00647BCF|MyApp.exe |uROServer.pas |TROServer |IntDispatchMessage |1328[27] | |00647ABC|MyApp.exe |uROServer.pas |TROServer |IntDispatchMessage |1301[0] | |0064782F|MyApp.exe |uROServer.pas |TROServer |DispatchMessage |1170[11] | |006477B4|MyApp.exe |uROServer.pas |TROServer |DispatchMessage |1159[0] | |006477A9|MyApp.exe |uROServer.pas |TROServer |DispatchMessage |1152[1] | |0064779C|MyApp.exe |uROServer.pas |TROServer |DispatchMessage |1151[0] | |00659CB6|MyApp.exe |uROLocalServer.pas |TROLocalServer |SendRequest |57[1] | |00659CA4|MyApp.exe |uROLocalServer.pas |TROLocalServer |SendRequest |56[0] | |0065A009|MyApp.exe |uROLocalChannel.pas |TROLocalChannel |IntDispatch |99[10] | |005EE540|MyApp.exe |uROClient.pas |TROTransportChannel |Dispatch |1884[36] | |005EE3FC|MyApp.exe |uROClient.pas |TROTransportChannel |Dispatch |1848[0] | |005EEC8F|MyApp.exe |uROClient.pas |TROTransportChannel |Dispatch |2134[27] | |00616EC8|MyApp.exe |PCCS_Intf.pas |TSentrol_Proxy |GetNewValues |6585[7] | |007CBDB9|MyApp.exe |ETAROConnectionForm.pas |TROConnectionForm |SyncSentrolUpdateTimerTimer |855[16] | |7C82ABE5|ntdll.dll | | |RtlTimeToTimeFields | | |004D5D9C|MyApp.exe |Controls.pas |TControl |WndProc |5063[0] | |004DA05B|MyApp.exe |Controls.pas |TWinControl |WndProc |7304[111] | |7C81A3AB|ntdll.dll | | |RtlLeaveCriticalSection | | |0042659C|MyApp.exe |Classes.pas |TThreadList |UnlockList |3359[1] | |00426598|MyApp.exe |Classes.pas |TThreadList |UnlockList |3359[1] | |004935BC|MyApp.exe |Graphics.pas | |FreeMemoryContexts |5060[12] | |00493524|MyApp.exe |Graphics.pas | |FreeMemoryContexts |5048[0] | |004D9799|MyApp.exe |Controls.pas |TWinControl |MainWndProc |7076[6] | |004329F4|MyApp.exe |Classes.pas | |StdWndProc |11583[8] | |7739C09A|USER32.dll | | |CallNextHookEx | | |004B1343|MyApp.exe |ExtCtrls.pas |TTimer |Timer |2281[1] | |00404A30|MyApp.exe |system.pas | |_CallDynaInst |9159[1] | |004B1227|MyApp.exe |ExtCtrls.pas |TTimer |WndProc |2239[4] | |004329F4|MyApp.exe |Classes.pas | |StdWndProc |11583[8] | |7739C42C|USER32.dll | | |GetParent | | |7739C45C|USER32.dll | | |GetParent | | |773A16E0|USER32.dll | | |DispatchMessageA | | |773A16D6|USER32.dll | | |DispatchMessageA | | |004CC234|MyApp.exe |Forms.pas |TApplication |ProcessMessage |8105[23] | |004CC138|MyApp.exe |Forms.pas |TApplication |ProcessMessage |8082[0] | |004CC26E|MyApp.exe |Forms.pas |TApplication |HandleMessage |8124[1] | |004CC264|MyApp.exe |Forms.pas |TApplication |HandleMessage |8123[0] | |004CC563|MyApp.exe |Forms.pas |TApplication |Run |8223[20] | |004CC4B0|MyApp.exe |Forms.pas |TApplication |Run |8203[0] | |007F18B3|MyApp.exe |MyApp.dpr | | |215[65] |
堆栈跟踪似乎是正常的,直到第一个TTimer调用之后,它包含一些垃圾(?),但是结尾包含似乎持有主线程的锁。
我可以相信这个堆栈跟踪吗? 如果没有,什么会导致这种情况,以及我如何避免它?
有关基于此堆栈跟踪的死锁的任何想法? 我不太了解如何创建一个datamodule可以死锁。
我正在使用德尔福2007年。
编辑:我发现一个DbExpress连接在主线程和RemObjects创建的线程之间共享的情况。 解决了这些问题后,应用程序已经运行了12小时以上,没有任何问题。 我会等待一两天,看看问题是否真的消失了。
我在关闭应用程序和在另一个线程中创建一个TForm或TDatamodule时遇到了同样的问题:因为应用程序正在终止,GlobalNameSpace(请参阅其他答案)被锁定(!),所以在另一个线程中创建TRORemoteDataModule锁定。 因为我用另一个锁来等待那个线程,所以我有一个死锁:-(。
在你的情况下,你必须看看其他线程,找到放置锁的那个(并且可能在等待,否则你不会发生死锁)。 我看到一个“SyncSentrolUpdateTimerTimer”:也许你在另一个线程的TDatamodule的创建中做了一个TThread.Synchronize?
编辑:如果你想在死锁时看看其他线程的堆栈:
http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx
http://code.google.com/p/map2dbg/
http://code.google.com/p/asmprofiler/wiki/ProcessStackViewer
据我所知,EurekaLog应该是可靠的。 如果包含函数< - >地址映射的信息与可执行文件的版本不同,则堆栈跟踪可能会变为无效。
我使用JCL进行堆栈跟踪日志记录,并将其与map / jdbg文件一起使用。 如果更改可执行文件并保留相同的映射文件,则堆栈日志将不正确,因为函数地址将不同。 所以也许唯一的原因可能是这个。 您还必须区分上次函数调用的真实堆栈跟踪和“通话历史记录”。 我使用通话记录,该记录还列出了记录时所调用的所有功能。 就像你的情况下的TTimer一样。
典型的堆栈跟踪只包含导致最后一个函数的函数调用。 另一方面,“通话记录”包含在特定时间框架内被调用的所有功能。 如果在主线程旁边有辅助线程(如TTimer),它也会记录他们的行为。 我忘记了这是如何在JCL中调用的,但是如果您在stRawMode中进行跟踪,这是默认行为。
最后,我可以从堆栈跟踪中看到WaitForSingleObject被调用,最好使用INFINITE参数,因此它永远不会超时。 然后WaitForSingleObject成为信号的条件永远不会全满。
检查“TRORemoteDataModule”以及它在构造函数中的作用。 因为它看起来只是从TDataModule继承而来,并且宣传了一些自己的逻辑。 这应该是造成死锁的原因。
编辑:
好的,我检查了TDataModule代码:
constructor TDataModule.Create(AOwner: TComponent);
begin
GlobalNameSpace.BeginWrite;
try
CreateNew(AOwner);
if (ClassType <> TDataModule) and not (csDesigning in ComponentState) then
begin
if not InitInheritedComponent(Self, TDataModule) then
raise EResNotFound.CreateFmt(SResNotFound, [ClassName]);
if OldCreateOrder then DoCreate;
end;
finally
GlobalNameSpace.EndWrite;
end;
end;
它使用“GlobalNameSpace”单例接口,它是这样定义和实现的:
var
GlobalNameSpace: IReadWriteSync;
initialization
{$IFDEF MSWINDOWS}
GlobalNameSpace := TMultiReadExclusiveWriteSynchronizer.Create;
{$ENDIF}
...
所以这里是你的锁。 现在有趣的是它发生的原因? 它看起来像一个标准的VCL代码。 也许你可以分享一些关于应用程序正在做什么的更多信息。
而且,你有办法查找调试输出。 这是在课堂上定义的:
procedure TMultiReadExclusiveWriteSynchronizer.BeginRead;
var
Thread: PThreadInfo;
WasRecursive: Boolean;
SentValue: Integer;
begin
{$IFDEF DEBUG_MREWS}
Debug('Read enter');
{$ENDIF}
...
所以如果定义了“DEBUG_MREWS”,你将通过“OutputDebugString”得到调试信息。 它应该解决问题。 对我来说,这看起来像一个组件初始化竞争条件。 :)
最后一次调用是在TMultiReadExclusiveWriteSynchronizer中,但它不显示在哪个方法中。 那里它可能调用Windows同步功能,并在那里被阻止。 你在使用RemObjects库吗? 那里发生了一些事情。 您可以使用SysInternals Process Explorer配置为下载Windows符号,并在进程运行时检查堆栈跟踪,如果以.dbg格式转换Delphi符号,您将拥有整个明确的调用堆栈。
链接地址: http://www.djcxy.com/p/91045.html