[yunqa.de] Re: YuOpenSSL : Memory leak when using library in thread
- From: Delphi Inspiration <delphi@xxxxxxxx>
- To: yunqa@xxxxxxxxxxxxx, "the_laser (Redacted sender the_laser for DMARC)" <dmarc-noreply@xxxxxxxxxxxxx>
- Date: Thu, 28 Jan 2021 17:18:24 +0100
On 27.01.2021 19:44, the_laser (Redacted sender the_laser for DMARC) wrote:
when using YuOpenSSL with Synapse , multiple memory leak occurs on
each HTTPS request, if request done in thread.
OpenSSL allocates memory to thread-local storage (TLS) for some TSL/SSL
operations. This memory must be freed before exiting the thread.
The OpenSSL function to free the memory allocated to TLS is
OPENSSL_thread_stop(). Failing to call OPENSSL_thread_stop() results in
memory leaks which cannot be recovered.
if using standard openssl libraries ( YuOpenSSL NOT defined ) - no
memory leaks.
The memory leak is the same with the OpenSSL DLLs - it ist just not
logged by the FastMM memory tracker because the DLLs use their own
memory manager.
ICS (Internet Component Suite) was also affected by this:
https://en.delphipraxis.net/topic/3920-7-memory-leaks-in-overbyteicswsocketpas-with-fixes/
The code below (and attached) fixes the leak.
Ralf
-----------------------------------------------------------------------
program YuOpenSSL_THTTPSend_Thread;
{$APPTYPE CONSOLE}
{$I DICompilers.inc}
{$R ..\Yunqa.res}
uses
{$IFDEF FastMM}{$I FastMM_uses.inc}{$ENDIF}
SysUtils, Classes,
httpsend, ssl_openssl, YuOpenSSL;
type
THTTPSend_Thread = class(TThread)
procedure Execute; override;
end;
procedure THTTPSend_Thread.Execute;
var
SynHttp: THTTPSend;
SL: TStringList;
begin
try
try
SynHttp := THTTPSend.Create;
try
SynHttp.HTTPMethod('GET', '
https://www.yunqa.de/delphi/');
SL := TStringList.Create;
try
WriteLn(SynHttp.Document.Position);
WriteLn(SynHttp.Document.Size);
SL.LoadFromStream(SynHttp.Document);
WriteLn(SL.Text);
finally
SL.Free;
end;
finally
SynHttp.Free;
end;
finally
{ Free OpenSSL thread-local storage (TLS).
THTTPSend may invoke OpenSSL TSL/SSL functions which allocate
memory to
thread-local storage. OPENSSL_thread_stop() frees this memory.
It is important to call OPENSSL_thread_stop() from the same
thread which
allocated the thread-local storage. Failing to do so results in
memory
leaks which cannot be recovered.
If THTTPSend is used within the main thread, YuOpenSSL calls
OPENSSL_thread_stop() automatically upon unit finalization. }
OPENSSL_thread_stop;
end;
except
on e: Exception do
WriteLn(e.ClassName, ': ', e.Message);
end;
end;
var
RunThread: THTTPSend_Thread;
begin
{$IFDEF FastMM}{$I FastMM_init.inc}{$ENDIF}
RunThread := THTTPSend_Thread.Create(True);
try
{$IFDEF COMPILER_15_UP}
RunThread.Start;
{$ELSE COMPILER_15_UP}
RunThread.Resume;
{$ENDIF COMPILER_15_UP}
RunThread.WaitFor;
finally
RunThread.Free;
end;
WriteLn('Done. Press ENTER to exit.');
ReadLn;
end.
program YuOpenSSL_THTTPSend_Thread;
{$APPTYPE CONSOLE}
{$I DICompilers.inc}
{$R ..\Yunqa.res}
uses
{$IFDEF FastMM}{$I FastMM_uses.inc}{$ENDIF}
SysUtils, Classes,
httpsend, ssl_openssl, YuOpenSSL;
type
THTTPSend_Thread = class(TThread)
procedure Execute; override;
end;
procedure THTTPSend_Thread.Execute;
var
SynHttp: THTTPSend;
SL: TStringList;
begin
try
try
SynHttp := THTTPSend.Create;
try
SynHttp.HTTPMethod('GET', '
https://www.yunqa.de/delphi/');
SL := TStringList.Create;
try
WriteLn(SynHttp.Document.Position);
WriteLn(SynHttp.Document.Size);
SL.LoadFromStream(SynHttp.Document);
WriteLn(SL.Text);
finally
SL.Free;
end;
finally
SynHttp.Free;
end;
finally
{ Free OpenSSL thread-local storage (TLS).
THTTPSend may invoke OpenSSL TSL/SSL functions which allocate memory to
thread-local storage. OPENSSL_thread_stop() frees this memory.
It is important to call OPENSSL_thread_stop() from the same thread which
allocated the thread-local storage. Failing to do so results in memory
leaks which cannot be recovered.
If THTTPSend is used within the main thread, YuOpenSSL calls
OPENSSL_thread_stop() automatically upon unit finalization. }
OPENSSL_thread_stop;
end;
except
on e: Exception do
WriteLn(e.ClassName, ': ', e.Message);
end;
end;
var
RunThread: THTTPSend_Thread;
begin
{$IFDEF FastMM}{$I FastMM_init.inc}{$ENDIF}
RunThread := THTTPSend_Thread.Create(True);
try
{$IFDEF COMPILER_15_UP}
RunThread.Start;
{$ELSE COMPILER_15_UP}
RunThread.Resume;
{$ENDIF COMPILER_15_UP}
RunThread.WaitFor;
finally
RunThread.Free;
end;
WriteLn('Done. Press ENTER to exit.');
ReadLn;
end.
Other related posts: