You are not logged in.
Hi @ab, I need write in a same log file from different threads (each thread is a DLL), when logging from multiples threads an error "file is un use by anoter application ..." is raised, I modified the TSynLog.CreateLogWriter for workaround this problem:
procedure TSynLog.CreateLogWriter;
var i,retry: integer;
exists: boolean;
begin
if fWriterStream=nil then begin
ComputeFileName;
if fFamily.NoFile then
fWriterStream := TFakeWriterStream.Create else begin
if FileExists(fFileName) then
case fFamily.FileExistsAction of
acOverwrite:
DeleteFile(fFileName);
acAppend:
Include(fInternalFlags,logHeaderWritten);
end;
for retry := 0 to 2 do begin
for i := 1 to 10 do
try
exists := FileExists(fFileName);
if exists and (fFamily.FileExistsAction<>acOverwrite) then begin
if fFamily.FileExistsAction=acAppend then
Include(fInternalFlags,logHeaderWritten);
end else
if (fFileRotationSize=0) or not exists then
TFileStream.Create(fFileName,fmCreate).Free; // create a void file
if (ptIdentifiedInOnFile = fFamily.fPerThreadLog) then \
fWriterStream := TFileStream.Create(fFileName, | This is my modification !!!
fmOpenReadWrite or fmShareDenyNone) // open with read/write sharing |
else /
fWriterStream := TFileStream.Create(fFileName,
fmOpenReadWrite or fmShareDenyWrite); // open with read sharing
break;
except
on Exception do
SleepHiRes(100);
end;
if fWriterStream<>nil then
break;
fFileName := ChangeFileExt(fFileName,'-'+fFamily.fDefaultExtension);
end;
end;
if fWriterStream=nil then // go on if file creation fails (e.g. RO folder)
fWriterStream := TFakeWriterStream.Create;
if (fFileRotationSize>0) or (fFamily.FileExistsAction<>acOverwrite) then
fWriterStream.Seek(0,soFromEnd); // in rotation mode, append at the end
end;
if fWriterClass=nil then
fWriterClass := TTextWriter;
if fWriter=nil then
fWriter := fWriterClass.Create(fWriterStream,fFamily.BufferSize);
fWriter.EndOfLineCRLF := fFamily.EndOfLineCRLF;
if integer(fFamily.EchoToConsole)<>0 then
fWriter.EchoAdd(ConsoleEcho);
if Assigned(fFamily.EchoCustom) then
fWriter.EchoAdd(fFamily.EchoCustom);
if Assigned(fFamily.fEchoRemoteClient) then
fWriter.EchoAdd(fFamily.fEchoRemoteEvent);
end;
The reason for this modification is because I need log the stack trace when exception is raised inside the DLL.
Are you agree with this modification and can you apply ?
Thank in advance.
Esteban Martin
Esteban
Offline
@ab, do you disagree with this modification ?
Thanks.
EM
Esteban
Offline
Sorry, what except/retry implementation ?
...
if (ptIdentifiedInOnFile = fFamily.fPerThreadLog) then
fWriterStream := TFileStream.Create(fFileName, fmOpenReadWrite or fmShareDenyNone)
else
fWriterStream := TFileStream.Create(fFileName, fmOpenReadWrite or fmShareDenyWrite);
...
The modification consist in open the file with fmShareDenyNone if PerThreadLog is ptIdentifiedInOnFile, I tested this modification and works fine, sure you could do better.
Thanks.
EM
Esteban
Offline
I think Arnaud means:
...
for retry := 0 to 2 do begin
for i := 1 to 10 do
try
...
break;
except
on Exception do
SleepHiRes(100);
end;
...
Offline
ups, I did not see that line.
Thanks oz, sorry ab.
EM
Esteban
Offline