#1 2014-07-15 07:52:14

edwinsn
Member
Registered: 2010-07-02
Posts: 1,218

TSynLog and multi-threading

Hi Arnaud,

I got an  error message something like "Cannot open myProgram.mab file, another program is using it" in my program, where multiple threads has their own TSynLog objects.

My derived TEyLog:

constructor TEyLogger.Create(const aLogFilePath: string; const aBufSize:
    Integer = 4096);
begin
  FSpecifiedLogFile := aLogFilePath;
  FSpecifiedBufferSize := aBufSize;
  inherited Create(nil);

  //by default accept all levels of logging
  Self.Family.Level := LOG_VERBOSE;
  Self.GenericFamily.Level := LOG_VERBOSE;
end;

procedure TEyLogger.CreateLogWriter;
begin
  if fWriterStream = nil then
  begin
    fFileName := FSpecifiedLogFile;

    if not FileExists(fFileName) then
      TFileStream.Create(fFileName, fmCreate).Free; // create a void file

    fWriterStream := TFileStream.Create(fFileName, // open it with read sharing
      fmOpenReadWrite or fmShareDenyWrite);
  end;

  if fWriter = nil then
  begin
    if FSpecifiedBufferSize < 64 then
      FSpecifiedBufferSize := fFamily.BufferSize;

    fWriter := SynCommons.TTextWriter.Create(fWriterStream, FSpecifiedBufferSize);
  end;
end;

Delphi XE4 Pro on Windows 7 64bit.
Lazarus trunk built with fpcupdelux on Windows with cross-compile for Linux 64bit.

Offline

#2 2014-07-15 19:13:01

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: TSynLog and multi-threading

This is an issue in this particular case.

Could you please create a ticket?

Offline

#3 2014-07-16 03:39:29

edwinsn
Member
Registered: 2010-07-02
Posts: 1,218

Re: TSynLog and multi-threading

done: http://synopse.info/fossil/tktview/ea4e … 3d017e997f

What would be the idea of fixing it?


Delphi XE4 Pro on Windows 7 64bit.
Lazarus trunk built with fpcupdelux on Windows with cross-compile for Linux 64bit.

Offline

#4 2014-07-16 07:17:32

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: TSynLog and multi-threading

Just let the .Mab file be opened by multiple threads at once.

Update:
It is weird, .mab file opening is already tread-safe.
It is opened with:

constructor TSynMemoryStreamMapped.Create(const aFileName: TFileName; aCustomSize: cardinal; aCustomOffset: Int64);
begin
  fFileStream := TFileStream.Create(aFileName,fmOpenRead or fmShareDenyNone);

My only option may be to put a critical section within TSynMapFile.Create() but it sounds weird...

Offline

#5 2014-07-17 05:41:05

edwinsn
Member
Registered: 2010-07-02
Posts: 1,218

Re: TSynLog and multi-threading

Thanks Arnaud, the problem's fixed. I guess fmShareDenyNone doesn't ensure thread-safety, I guess the problem was that, Thread B trying to open the same .mab file while thread A hasn't done its opening of the very same file.


Delphi XE4 Pro on Windows 7 64bit.
Lazarus trunk built with fpcupdelux on Windows with cross-compile for Linux 64bit.

Offline

#6 2014-07-17 06:24:54

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Re: TSynLog and multi-threading

It does make sense.

It is very good that you did identify this issue.
On our side, we only used one TSynLog instance, so we did not occur such a problem.

Thanks for the feedback.

Offline

#7 2014-07-17 08:21:20

edwinsn
Member
Registered: 2010-07-02
Posts: 1,218

Re: TSynLog and multi-threading

Arnaud, you are welcome! You have done a great work!


Delphi XE4 Pro on Windows 7 64bit.
Lazarus trunk built with fpcupdelux on Windows with cross-compile for Linux 64bit.

Offline

#8 2014-07-17 15:28:05

mpv
Member
From: Ukraine
Registered: 2012-03-24
Posts: 1,571
Website

Re: TSynLog and multi-threading

It's not a subject of this topic, but another potential issue (from my POV) is in TMemoryMap.Map (called by TSynMemoryStreamMapped).
If file is 0 length TMemoryMap.Map return false and I got the exception. I fix this behavior many time in my code (not map file related), but may be it must be fixed in the synCommons just replace

if (fFileSize<=0) or (fFileSize>maxInt) then

with

if (fFileSize<0) or (fFileSize>maxInt) then

in  TMemoryMap.Map?

UPD. UPS - CreateFileMapping(...) fail in this case....

Last edited by mpv (2014-07-17 15:34:37)

Offline

#9 2014-07-17 16:54:43

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,661
Website

Offline

#10 2014-08-06 07:58:41

mpv
Member
From: Ukraine
Registered: 2012-03-24
Posts: 1,571
Website

Re: TSynLog and multi-threading

Thanks! I remove my hacks and everything work well with 0 length file.

Offline

Board footer

Powered by FluxBB