1

When dwsExprs is added to a DLL, his finalization section freeze. Actaully TdwsGuardianThread.Finalize is frozen on the line guardian.WaitFor.

To demonstrate the issue, I made a sample DLL, which is empty and only include dwsCript. I also made a test application loading the DLL and freeing it immediately. On exit the application freeze as I said above (Put a breakpoint on guardian.WaitFor to see that.

Sample DLL:

library DlltestDll;

uses
  dwsExprs;

{$R *.res}

begin
end.



Sample application:

program DllTest;

{$APPTYPE CONSOLE}

{$R *.res}

uses
    Windows;

var
    HDll : HMODULE;
begin
    HDll := LoadLibrary('DllTestDll.dll');
    FreeLibrary(HDll);
end.

I'm using XE4 and DWScript extracted from SVN repository may 26.

Any help appreciated.

fpiette
  • 11,983
  • 1
  • 24
  • 46
  • If found this article: http://qc.embarcadero.com/wc/qcmain.aspx?d=29843. I've not tryed but it looks very similar to the issue here. – fpiette May 30 '13 at 11:12
  • In the above article, there was a comment saying "you should not try and cleanup threads in the finalization of units that might be included in a dll". I tryed this advice and it works. The workaround as I implemented it is to add an exported funtion in the DLL which calls TdwsGuardianThread.Finalize and call that exported function from the main application before unloading the DLL. Later when dwsExprs finalization section is called, the guardian thread is already stopped and nothing freeze anymore. – fpiette May 30 '13 at 11:35
  • A real fix for this issue could be to defer creating the guardian thread until the first script is run, and to destroy it each time the last script terminates. This way there will be no guardian thread running when the unit finalizes nad no freeze would occur. – fpiette May 30 '13 at 11:35
  • Deferring the creation wouldn't be problematic, but releasing the thread each time the last script terminates would impact applications that execute lots of small scripts one at a time, as they would take a major hit creating/starting/stopping/destroying the thread each time (and in "normal" executions, the guardian thread is just overhead) – Eric Grange May 31 '13 at 09:30

1 Answers1

2

The solution as DWScript is currently is the workaround I described in the comments above:

Add an exported function in the DLL which calls TdwsGuardianThread.Finalize and call that exported function from the main application before unloading the DLL. Later when dwsExprs finalization section is called, the guardian thread is already stopped and nothing freeze anymore



The sample DLL now looks like:

library DlltestDll;

uses
  dwsExprs;

{$R *.res}

procedure Finalize; stdcall;
begin
   TdwsGuardianThread.Finalize;
end;

exports
   Finalize;

begin
end.



And the sample application is:

program DllTest;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Windows;

var
    HDll : HMODULE;
    Finalize : procedure; stdcall;
begin
    HDll := LoadLibrary('DllTestDll.dll');

    @Finalize := GetProcAddress(HDll, 'Finalize');
    Finalize;

    FreeLibrary(HDll);
end.
BenMorel
  • 34,448
  • 50
  • 182
  • 322
fpiette
  • 11,983
  • 1
  • 24
  • 46