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.