Recent

Author Topic: debugln (in and out of threads)  (Read 2122 times)

dbannon

  • Hero Member
  • *****
  • Posts: 3215
    • tomboy-ng, a rewrite of the classic Tomboy
debugln (in and out of threads)
« on: May 25, 2024, 08:11:50 am »
Hi Folks, I just spotted something that puzzles me.

Firstly, a problem where the first call to debugln appears in a thread caused some memory leaks and some other, very strange crashes way after the threaded code. The debugln wiki page talks about debugln as being threadsafe but its creation/setup/destruction is not. Its not clear to me just how that happens, but I quickly found a call to debugln('') before the thread code fixed my problem.

But I also saw talk about "use" LazLogger only in the main unit and LazLoggerBase everywhere else, implying that in my code, where I "use" LazLogger in, maybe 25 units, it is doing that "setup/creation/destruction" in all 25 units ?

My tests indicate thats not the the case, putting my dummy call to debugln('') in the mainunit fixed my problem elsewhere even though the other unit had its own LazLogger.

So, questions -

  • Is making a dummy call, debugln('') in main the correct way to ensure its created/setup before we hit any thread code ?
  • Is there any advantage in just using LazLoggerBase in all units except the main one ?


Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

af0815

  • Hero Member
  • *****
  • Posts: 1381
Re: debugln (in and out of threads)
« Reply #1 on: May 25, 2024, 09:56:07 am »
IMHO is all according the Lazarus wiki

a ) I use the first (and last) call in my lpr files, so i can also detect if my mainform is not created, but the app is started. And it is meaningless on what system/cpu i am working/running
b ) It have the advantage to control in one place if you want the functinallity of LazLogger or only use dummy stub's. And only there i use conditional compiling for debug, and release.

This is based on long term using of LazLogger with WIndows/Linux/Raspbian.
regards
Andreas

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 10798
  • Debugger - SynEdit - and more
    • wiki
Re: debugln (in and out of threads)
« Reply #2 on: May 25, 2024, 04:34:19 pm »
Well, it is supposed to be threadsafe. If it has bugs they need to be reported and addressed.

The memory leak I have indeed seen too, but not yet had time to take care of it. (Also I can't reproduce it at will).

In which units you use LazLogger vs LazLoggerBase does not matter. As long as you have LazLogger in at least one unit. All that does is it registers the real logger. LazLoggerBase registers a logger that discards everything.

Mind https://wiki.freepascal.org/LazLogger#Multithreading
Quote
The creation/setup/destruction/configuration of the logger is not thread-safe

And, I just spotted this also said:
Quote
Creation is usually done automatically during unit initialization.
which is wrong.
If you don't call "LazLogger" (the property), then creation is done in the first call to "debugln" (or dbgout). I changed that.

So if your first debugln happens while you already have threads, and several debugln attempt to create the logger, then that is a problem (which was meant to be documented, and now is documented).

To remedy, just access the "LazLogger" property once before starting any thread.

If other parts fail within threads for you, then please report that.



Mind you can try and play around with LazLogger.FileHandle.

By default it is set to
Code: Pascal  [Select][+][-]
  1. LazLogger.FileHandle := TLazLoggerFileHandleMainThread.Create;
If you change that, you must repeat changes you made to the "LogName" or "UseStdOut" properties.

There is another class called TLazLoggerFileHandleThreadSave.

It will do logging inside each thread (the OS/WS must allow file-handles to be accessed from different threads / done in critical section).
On the upside, you main thread doesn't need to run Synchronize. (Normally done automatically, if you have a standard GUI app)

On the downside, if your StdOut or filehandle isn't yet open, and your first debugln is in a thread the TLazLoggerFileHandleThreadSave will create the handle inside this thread. And on some OS/WS it will become unusable if that thread terminates.
TLazLoggerFileHandleMainThread does always create handles in the main thread (IIRC / it should).

dbannon

  • Hero Member
  • *****
  • Posts: 3215
    • tomboy-ng, a rewrite of the classic Tomboy
Re: debugln (in and out of threads)
« Reply #3 on: May 26, 2024, 03:21:01 am »

Thanks Anton, Martin.

Well, it is supposed to be threadsafe. If it has bugs they need to be reported and addressed.
Well, no, I don't think its a bug but the documentation needed to be more explicit, your edit fixes that, I have just added a touch more to emphasis the key issue. 

I am totally convinced the exceptions and memory leaks ONLY occur if the first call to debugln() happens in a thread. So don't do that !

Thanks for your help !

Davo
Lazarus 3, Linux (and reluctantly Win10/11, OSX Monterey)
My Project - https://github.com/tomboy-notes/tomboy-ng and my github - https://github.com/davidbannon

 

TinyPortal © 2005-2018