[fpc-pascal] Are the TEncoding singletons thread-safe?
silvioprog
silvioprog at gmail.com
Thu Aug 11 03:05:16 CEST 2016
Hello,
I've used the useful singletons available in the TEncoding class, and I
don't get any problem with them, unless using threads.
I have an application that does many tests in a code compilable in FPC and
Delphi, however, the FPC's tests raise memory leak at the finalization
tests. The problem can be a little bit hard to be reproduce, but I think
the code below can do that:
=== begin code [project1.dpr] ===
program project1;
{$IFDEF FPC}
{$MODE DELPHI}
{$ENDIF}
{$IFDEF MSWINDOWS}
{$APPTYPE CONSOLE}
{$ENDIF}
uses
// HeapTrc, the FPC staff recomends to enable HeapTrc in the lpi or
passing the -gh compiler parameter
{$IFDEF UNIX}
CThreads,
{$ENDIF} SysUtils, Classes;
type
TTestThread = class(TThread)
public
constructor Create;
procedure Execute; override;
end;
constructor TTestThread.Create;
begin
inherited Create(True);
FreeOnTerminate := False;
end;
procedure TTestThread.Execute;
begin
WriteLn(TEncoding.Default.GetString(TBytes.Create(65, 66, 67)));
end;
var
VThread1, VThread2: TTestThread;
begin
{$IFNDEF FPC}
ReportMemoryLeaksOnShutdown := True;
{$ENDIF}
VThread1 := TTestThread.Create;
VThread2 := TTestThread.Create;
try
Sleep(1000);
VThread1.Start;
VThread2.Start;
VThread1.WaitFor;
VThread2.WaitFor;
finally
VThread1.Free;
VThread2.Free;
end;
end.
=== end code ===
If you compile and run the code above, you may get the following trace:
=== begin log ===
ABC
ABC
Heap dump by heaptrc unit
44 memory blocks allocated : 2119/2144
43 memory blocks freed : 2087/2112
1 unfreed memory blocks : 32
True heap size : 131072
True free heap : 131072
Should be : 130912
Call trace for block $00007FFFF7FAB0C0 size 32
=== end log ===
Researching the FPC's TEncoding implementation, I think it doesn't do any
lock before instantiate its singletons, so I decided to research how Delphi
implements it, because I can't get any error on it, and I've seen it
implements a "lock-free initialization" technique
<http://stackoverflow.com/a/24657705/3268398> using the XE's
AtomicCmpExchange() function before return any TEncoding global instance.
That memory leak can be really a problem, because I can't prevent how many
threads will call the TEncoding's singletons at same time, I could
initialize the TEncoding before starting any thread of my application, but
it doesn't sound good, because I can't prevent if the threads will
instantiate the ANSI or UTF8 singleton. The best way to solve this problem
would be making the TEncoding become thread-safe. I could send a patch to
solve it, but I don't know if FPC provides some global locker like
AtomicCmpExchange.
--
Silvio Clécio
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-pascal/attachments/20160810/9036780f/attachment.html>
More information about the fpc-pascal
mailing list