首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >德尔福EurekaLog和OmniThreadLibrary不兼容?

德尔福EurekaLog和OmniThreadLibrary不兼容?
EN

Stack Overflow用户
提问于 2021-02-15 09:59:14
回答 1查看 171关注 0票数 2

我有一个简单的程序,它在单元的“初始化”中创建一个OmniThread工作池,并在该单元的“终结”过程中销毁相同的池。只要我们不使用EurekaLog,它就能正常工作。如果我们包括EurekaLog,则在应用程序的最后定稿过程中(在关闭应用程序之后)会引发访问冲突。这只会每3到10次程序结束一次,所以似乎出现了某种时间问题。

如果我们在“正常”应用程序流中创建工作池(而不是在独立单元的初始化和最后确定过程中),那么它似乎都能正常工作。

该单位的代码如下:

代码语言:javascript
复制
unit Unit1;

interface

uses
  OtlParallel;

var
  _Worker: IOmniBackgroundWorker;

implementation

initialization
  _Worker := Parallel.BackgroundWorker.NumTasks(10)
    .Execute(
      procedure(const AWorkItem: IOmniWorkItem)
      begin
        //
      end
    );

finalization
  _Worker.Terminate(INFINITE);
  _Worker := nil;

end.

主要应用程序也很简单:

代码语言:javascript
复制
uses
  {$IFDEF EurekaLog}
  EMemLeaks,
  EResLeaks,
  EDebugExports,
  EDebugJCL,
  EFixSafeCallException,
  EMapWin32,
  EAppVCL,
  EDialogWinAPIMSClassic,
  EDialogWinAPIEurekaLogDetailed,
  EDialogWinAPIStepsToReproduce,
  ExceptionLog7,
  {$ENDIF EurekaLog}
  Vcl.Forms,
  Unit1 in 'Unit1.pas';

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.Run;
end.

访问冲突的调用堆栈是:

代码语言:javascript
复制
:5653e4c4 
OtlTaskControl.TOmniTask.Execute
OtlThreadPool.TOTPWorkerThread.ExecuteWorkItem($393A160)
OtlThreadPool.TOTPWorkerThread.Execute
System.Classes.ThreadProc($3976800)
EThreadsManager.NakedBeginThreadWrapper(???)
:76ee6359 KERNEL32.BaseThreadInitThunk + 0x19
:77628944 ntdll.RtlGetAppContainerNamedObjectPath + 0xe4
:77628914 ntdll.RtlGetAppContainerNamedObjectPath + 0xb4

我使用了最新的OTL和EurekaLog版本7.9.1.4更新1热修复4的主签出。

我们创建和破坏工人池的方式正确吗?如果是这样的话,是否有人熟悉OTL/EurekaLog中的问题(如果它们一起使用)?

EN

回答 1

Stack Overflow用户

发布于 2021-02-16 13:17:37

这似乎是一个缺陷/未在OTL中实现:

代码语言:javascript
复制
destructor TOmniTaskControl.Destroy;
begin
  // TODO 1 -oPrimoz Gabrijelcic : ! if we are being scheduled, the thread pool must be notified that we are dying !

看起来,这段代码可以在线程池中释放一个任务,该线程池仍在运行。

TOmniTaskControlTOmniTask共享同一个TOmniSharedTaskInfo实例。如果从TOmniTaskControl的终结中删除了OtlTaskControl,那么仍在运行的线程池中的任何TOmniTask都将包含对已经删除的TOmniSharedTaskInfo的引用。

在没有EurekaLog的应用程序中,这“不是一个问题”,因为删除对象的内存将保持不变。因此,对已删除对象的访问将是成功的。但是,添加EurekaLog意味着用调试模式擦除已释放的内存。因此,访问已删除的对象可能会失败。

具体来说,当TOmniTask试图访问已删除的TOmniSharedTaskInfo时,代码会崩溃。

代码语言:javascript
复制
procedure TOmniTask.InternalExecute(calledFromTerminate: boolean);
// ...
begin
  otCleanupLock.EnterWriteLock;
// ...
      finally
        otCleanupLock.EnterWriteLock;
        if assigned(otSharedInfo_ref.ChainTo) and
           (otSharedInfo_ref.ChainIgnoreErrors or (otExecutor_ref.ExitCode = EXIT_OK))
        then
          chainTo := otSharedInfo_ref.ChainTo; // - fails here inside System.@IntfCopy
        otSharedInfo_ref.ChainTo := nil;
// ...

不可访问的:5653e4c4位置只是一个地址,System.@IntfCopy在从otSharedInfo_ref中删除字段时试图读取该地址。

您可以通过禁用EurekaLog中的“捕捉内存问题”选项(在处理时覆盖对象/接口VMT )并将“何时释放”选项设置为“什么都不做”,从而确认这是一个“空闲后使用”问题。如果您这样做--前面提到的访问已删除的otSharedInfo_ref / TOmniSharedTaskInfoTOmniTask.InternalExecute中的崩溃将不再发生(实际上--因为现在已删除的otSharedInfo_ref将保持不变,因此将是可访问的)。

此外,现在将发现一个新的内存泄漏:

代码语言:javascript
复制
OtlSync.pas TOmniCriticalSection.Create
OtlSync.pas CreateOmniCriticalSection
OtlSync.pas TOmniCS.Initialize
OtlTaskControl.pas TOmniCS.Acquire
OtlTaskControl.pas TOmniTask.InternalExecute
OtlTaskControl.pas TOmniTask.Execute
OtlThreadPool.pas TOTPWorkerThread.ExecuteWorkItem
OtlThreadPool.pas TOTPWorkerThread.Execute
System.Classes.pas ThreadProc

此泄漏发生在otSharedInfo_ref.MonitorLock.Acquire at TOmniTask.InternalExecute。这发生在前面提到的chainTo := otSharedInfo_ref.ChainTo附近。

这只是“免费后使用”bug的又一次确认。这是因为通常在删除ostiMonitorLock: TOmniCriticalSection字段作为TOmniSharedTaskInfo销毁的一部分时,otSharedInfo_ref: TOmniSharedTaskInfo字段将被最后确定。

但是,如果存在“免费后使用”错误--那么TOmniTaskControl将被删除,而TOmniTask活动时仍保留对同一个TOmniSharedTaskInfo的引用。这意味着尝试otSharedInfo_ref.MonitorLock.Acquire将使用全新的关键部分重新初始化ostiMonitorLock: TOmniCriticalSection。而且,由于TOmniTaskControl和它的TOmniSharedTaskInfo已经消失了,所以不会有任何代码来清理这个新创建的关键部分。实际上,您刚刚创建了一个新的关键部分,作为已删除对象(TOmniSharedTaskInfo)中的字段!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66205938

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档