[Lazarus] Memory leak with Synchronize on external threads
Stefan Schalk
schalk.stefan at googlemail.com
Tue May 31 14:37:30 CEST 2016
Hi everybody,
for the demonstration of the memory leak I created a small application.
This makes it easier to reproduce.
The demo starts threads - one after another.
A timer will trigger the thread starts.
The timer waits for the previously started thread to finish, cleans up and
starts a new thread.
The thread's function will only forward to a method of the main form by using
"TThread.Synchronize".
The method in the main form will increase a counter and shows it in a label.
That's all.
While running the application you can observe the increasing memory consumption
with MS Taskmanager, Proccess Explorer or the like.
To create the demo application use Lazarus 1.6 and place a TLabel and a TTimer
component on your main form.
The timer gets an interval of 200ms and is initially disabled.
If you use TThread.Synchronize call, memory will start to leak.
Without the snycronize call there is no leak.
Can anybody acknowledge my finding?
Is there already a fix for this?
Best regards,
Stefan
// - - - - - Start of the demo code - - - - -
unit main;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
ExtCtrls
{, JwaPsApi, JwaWinBase};
type
TForm1 = class(TForm)
Counter_Label: TLabel;
//Memory_Label: TLabel;
Timer1: TTimer;
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure SyncExecute;
procedure Timer1Timer(Sender: TObject);
private
FCounter : Integer;
FmyThreadID : TThreadID;
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
FCounter := 0;
FmyThreadID := 0;
end;
procedure TForm1.FormShow(Sender: TObject);
begin
Timer1.Enabled := true;
end;
procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
Timer1.Enabled := false;
if FmyThreadID <> 0 then
begin
WaitForThreadTerminate(FmyThreadID, 2000);
CloseThread(FmyThreadID);
FmyThreadID := 0;
end;
CloseAction := caFree;
end;
procedure TForm1.SyncExecute;
begin
Inc(FCounter);
Counter_Label.Caption := IntToStr(FCounter);
end;
function myThreadFunc(parameter : pointer) : ptrint;
begin
TThread.Synchronize(nil, @Form1.SyncExecute);
EndThread;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
//var
// pmc: _PROCESS_MEMORY_COUNTERS;
begin
Timer1.Enabled := false;
if FmyThreadID <> 0 then
begin
WaitForThreadTerminate(FmyThreadID, 2000);
CloseThread(FmyThreadID);
FmyThreadID := 0;
end;
FmyThreadID := BeginThread(@myThreadFunc, nil);
{
pmc.cb := SizeOf(pmc);
if GetProcessMemoryInfo(GetCurrentProcess(), pmc, pmc.cb) then
begin
Memory_Label.Caption := IntToStr(pmc.WorkingSetSize) + ' Bytes';
end
else Memory_Label.Caption := 'Unable to get process info!';
}
Timer1.Enabled := true;
end;
end.
// - - - - - End of the demo code - - - - -
Von: Stefan Schalk [mailto:schalk.stefan at googlemail.com]
Gesendet: Donnerstag, 26. Mai 2016 11:07
An: Lazarus Mailing List <lazarus at lists.lazarus.freepascal.org>
Betreff: [Lazarus] Memory leak with Synchronize on external threads
There is a memory consumption/leak using the TThread.Synchronize function.
A callback function is called out of another ("external") thread (from an
loaded DLL).
Inside the callback function a synchronized call to a procedure has to be done.
Every thing works without error, but there is a memory use increasement during
the TThread.Synchronize call.
procedure OnExternalThreadCallback(...); cdecl;
begin
...
TThread.Synchronize(nil, @MyMainClass.CallbachSyncedWithMainThread);
...
end;
The external thread are created/used/freed like discussed in the Lazarus
mailing list:
Mutlithreaded Dll Callback crashes my Application
<http://lists.lazarus.freepascal.org/pipermail/lazarus/2010-August/054728.html>
The memory leak problem arises with Lazarus 1.6.0 and FPC 3.0.0.
Under the hood the processing of the TThread.Synchronize changed.
Lazarus 1.4.4 with FPC 2.6.4 didn't have this problem.
I don't have the versions between 1.4.4 and 1.6.0, therefore I cannot say
something about them (if there are any).
-------------- next part --------------
A non-text attachment was scrubbed...
Name: winmail.dat
Type: application/ms-tnef
Size: 12762 bytes
Desc: not available
URL: <http://lists.lazarus-ide.org/pipermail/lazarus/attachments/20160531/7c8457e5/attachment-0002.bin>
More information about the Lazarus
mailing list