Recent

Author Topic: freopen and fpc?  (Read 4218 times)

Soner

  • Sr. Member
  • ****
  • Posts: 305
Re: freopen and fpc?
« Reply #15 on: April 24, 2021, 06:43:29 pm »
@Warfley: I try this:

Code: Pascal  [Select][+][-]
  1. program errorlog;
  2. ...
  3. begin
  4.    Assign(StdErr, 'error.log');
  5.    Rewrite(StdErr);
  6.   ...
  7.    Application.run;
  8.    Close(StdErr);
  9.  end.

A empty error.log is created but console-messages are still there.


Warfleys recommendation works on Windows. I see no messages on console:
Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. uses
  6.   {$IFDEF UNIX}{$IFDEF UseCThreads}
  7.   cthreads,
  8.   {$ENDIF}{$ENDIF}
  9.   Classes, SysUtils
  10.   { you can add units after this };
  11.  
  12. {$DEFINE ERRLOGFILE}  //<--undefine for errors on console
  13. begin
  14.   try
  15.   {$IfDef ERRLOGFILE}
  16.   AssignFile(StdErr, 'stderr.txt');  //<-- CHANGE PATH
  17.   Rewrite(StdErr);
  18.   {$endif}
  19.  
  20.   WriteLn(StdErr,'error');
  21.  
  22.   {$IfDef ERRLOGFILE}
  23.   CloseFile(StdErr);
  24.   {$endif}
  25.  
  26.   except
  27.     on E: EInOutError do
  28.         Writeln('File handling error occurred. Details: ', E.ClassName, '/', E.Message);
  29.   end;
  30.  
  31.  
  32.  {$IfNDef ERRLOGFILE}
  33.   Writeln(StdOut,'Look at Errorfile');
  34.  {$endif}
  35.   readln;
  36. end.
  37.  

Fred vS

  • Hero Member
  • *****
  • Posts: 3168
    • StrumPract is the musicians best friend
Re: freopen and fpc?
« Reply #16 on: April 24, 2021, 07:59:52 pm »
@Warfley: Thanks, I will study your code, write you later.

@Soner: Thanks too but what is the difference with my original code?
Like explained, of course this will work for the errors generate by fpc himself, but all other errors from dependencies or libraries will not be redirected and you will see them on console, for Windows and Unix too.

Fre;D
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Fred vS

  • Hero Member
  • *****
  • Posts: 3168
    • StrumPract is the musicians best friend
Re: freopen and fpc?
« Reply #17 on: April 25, 2021, 11:42:13 am »
I think the problem is the following, when using Assign, AssignFile or AssignStream, what happens is that the handling of the "Text" object in pascal is changed. The problem is that the other code seems to send the data to stderr not via the pascal Text object, but rather via the filedescriptor and the operating system commands (e.g. fwrite on posix), thereby circumventing the Text handler completely.

So to target this problem you need to change the file handling on the OS level. I don't know much about the windows API with regards to this topic, but on POSIX systems you have the dup2 command available: Link. dup2 can be thought of as a form of redirect meaning dup2(filedescriptor, stderr) will make every write to stderr be a write to the same file as filedescriptor.

So you can try out something like this:
Code: Pascal  [Select][+][-]
  1. uses BaseUnix;
  2. ...
  3. var errFileHandle: Integer;
  4.  
  5. function MapStdErrToFile(const FileName: String): Boolean;
  6. begin
  7.  
  8.  errFileHandle := FpOpen(FileName, O_Creat, O_WrOnly);
  9.   Result := FpDup2(errFileHandle, StdErrorHandle) >= 0;
  10. end;


Hello Warfley.

I tested your code: there are excellent news (and other less good).

Doing this:

Code: Pascal  [Select][+][-]
  1. program errorlog;
  2.     ...
  3.     var
  4.      errFileHandle: Integer;
  5.     begin
  6.        if fileexists('error.log') then deletefile('error.log');  // needed otherwise works only once
  7.  
  8.       errFileHandle := FpOpen('error.log', O_Creat, O_WrOnly);
  9.        FpDup2(errFileHandle, StdErrorHandle);
  10.         ...
  11.        Application.run;
  12.     end.

Does not show any message on console.  ;D

But the error.log file is empty and cannot be accessed (no permission).

I did change with FpOpen('error.log', O_Creat, O_RDWR); but did not help, the file is still empty.

Also it works only once, when 'error.log' was created it must be deleted before to re-run the application otherwise message appears again.

Fre;D





« Last Edit: April 25, 2021, 03:32:38 pm by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

Warfley

  • Hero Member
  • *****
  • Posts: 1499
Re: freopen and fpc?
« Reply #18 on: April 25, 2021, 04:25:28 pm »
Ok, fpOpen seems to be weird, but you can use filestreams an grab the handle:
Code: Pascal  [Select][+][-]
  1. uses
  2.   Classes, BaseUnix;
  3.  
  4. var
  5.   fs: TFileStream;
  6. begin
  7.   fs := TFileStream.Create('error.txt', fmOpenReadWrite or fmCreate);
  8.   try
  9.     FpDup2(fs.Handle, StdErrorHandle);
  10.     FpWrite(StdErrorHandle, 'Hello World'#10, 12);
  11.   finally
  12.     fs.Free;
  13.   end;
  14. end.
  15.  

Works fine on my Linux

Fred vS

  • Hero Member
  • *****
  • Posts: 3168
    • StrumPract is the musicians best friend
Re: freopen and fpc?
« Reply #19 on: April 25, 2021, 04:57:21 pm »
Ok, fpOpen seems to be weird, but you can use filestreams an grab the handle:
Code: Pascal  [Select][+][-]
  1. uses
  2.   Classes, BaseUnix;
  3.  
  4. var
  5.   fs: TFileStream;
  6. begin
  7.   fs := TFileStream.Create('error.txt', fmOpenReadWrite or fmCreate);
  8.   try
  9.     FpDup2(fs.Handle, StdErrorHandle);
  10.     FpWrite(StdErrorHandle, 'Hello World'#10, 12);
  11.   finally
  12.     fs.Free;
  13.   end;
  14. end.
  15.  

Works fine on my Linux

Hello Warfley.

Yep, you are still the Greatest Champion.

with this:

Code: Pascal  [Select][+][-]
  1. program errorlog;
  2.         ...
  3.         var
  4.          fs: TFileStream;
  5.         begin
  6.            fs := TFileStream.Create('error.log', fmOpenReadWrite or fmCreate);
  7.            FpDup2(fs.Handle, StdErrorHandle);
  8.            ...
  9.            Application.run;
  10.            fs.free;
  11.         end.

No more error messages on console but a beautiful error.log file with all the messages from libraries and dependencies included, no memory leak.

That's the way I like it.  ;)

Many thanks Warfley.

Fre;D
« Last Edit: April 25, 2021, 05:00:29 pm by Fred vS »
I use Lazarus 2.2.0 32/64 and FPC 3.2.2 32/64 on Debian 11 64 bit, Windows 10, Windows 7 32/64, Windows XP 32,  FreeBSD 64.
Widgetset: fpGUI, MSEgui, Win32, GTK2, Qt.

https://github.com/fredvs
https://gitlab.com/fredvs
https://codeberg.org/fredvs

 

TinyPortal © 2005-2018