How do I avoid crash during my widget init thanks to NULL fl_graphics_driver pointer in FLTK 1.4?

27 views
Skip to first unread message

Paul Hahn

unread,
Jan 21, 2023, 9:06:08 AM1/21/23
to fltk.general
I have a number of unit tests for widgets I have written that are now segfaulting in my constructor thanks to trying to call a function  like fl_font(), seemingly before the graphics driver is initialized. The segfault happens because the FLTK internals pointer fl_graphics_driver is NULL. For example,

program received signal SIGSEGV, Segmentation fault.
0x0000555555d1b5f0 in fl_font () at .../FL/fl_draw.H:790
790      return fl_graphics_driver->font();

Actually, I have a subclass  of Fl_Double_Window that contains a member of my widget class. The crash happens when the window is created in my main() and before it is shown or fl::run() is called..

This code and unit test has been around and working for a long time before this. Unfortunately, I haven't been running it in the recent month or so. But I just did and now this weirdness shows up! Is there some new trickiniess in FLTK 1.4 that I need to attend to for things like this to work now?


Paul Hahn

unread,
Jan 21, 2023, 9:27:45 AM1/21/23
to fltk.general
OK it seems now I have to explicitly call fl_font(fontNum,fontSize) in my main() to initially set a font + size before any of my other code calls fl_font(). Looks like calling fl_font(fontNum,fontSize) defines the FLTK internal fl_graphics_driver variable properly.

I suppose in the past calling fl_font() before explicitly setting a font + size must have returned some kind of default (???) since I had not been seeing this crash before.

Anyway, things are good now. Thanks for reading.
 

Matthias Melcher

unread,
Jan 21, 2023, 11:37:24 AM1/21/23
to fltk.general
tl;dr you can call fl_open_display() first to make sure that the graphics driver exists

The current solution is not the best solution, and it should not break existing code. The background is the use of FLUID and other tools in the command line. Depending on the OS, opening a connection to the display may throw an error if the tool is intended for the command line. So we try to leave all measuring of fonts and other machine relevant data until the app calls `show()`. This works generally very well, because font size commonly don't need to be known until a widget is shown or drawn. But as we see here, this is not always the case and can not always be expected from the user.

I hope we find a solution to that soon. Probably just calling fl_open_display() whenever the graphics driver is requested, but not yet initialised, ie enough. Other core devs?

Greg Ercolano

unread,
Jan 21, 2023, 1:01:05 PM1/21/23
to fltkg...@googlegroups.com


On 1/21/23 08:37, 'Matthias Melcher' via fltk.general wrote:
The current solution is not the best solution, and it should not break existing code. The background is the use of FLUID and other tools in the command line. Depending on the OS, opening a connection to the display may throw an error if the tool is intended for the command line. So we try to leave all measuring of fonts and other machine relevant data until the app calls `show()`. This works generally very well, because font size commonly don't need to be known until a widget is shown or drawn. But as we see here, this is not always the case and can not always be expected from the user.

    I think too, IIRC, the font system initialization overhead is significant enough on some
    platforms should be delayed until absolutely necessary. Esp. so that in FLTK applications
    that even draw any text (pure graphics, like a speedometer on embedded hardware)
    the overhead can be avoided.


I hope we find a solution to that soon. Probably just calling fl_open_display() whenever the graphics driver is requested, but not yet initialised, ie enough. Other core devs?


    I think the OP's problem (which he's since corrected) is probably one of assuming
    a font had already been set, as I *think* what he's saying is he called the getter
    version of fl_font(), e.g. "fl_font(void)", without having first called fl_font(face,size) to set it,
    which probably would have yielded "undefined behavior".

    Anyway, he's since fixed the problem.

    It's certainly a valid use (and documented) to call fl_font() outside of draw(),
    such as to measure text with fl_measure() during widget construction, before graphics
    has been initialized. I'm guessing fl_font(face,size) checks if graphics has not yet been
    initialized, and initializes it.. but fl_font(void) does not (and perhaps shouldn't)

Greg Ercolano

unread,
Jan 21, 2023, 1:19:14 PM1/21/23
to fltkg...@googlegroups.com

On 1/21/23 10:01, Greg Ercolano wrote:

On 1/21/23 08:37, 'Matthias Melcher' via fltk.general wrote:

The current solution is not the best solution, and it should not break existing code. The background is the use of FLUID and other tools in the command line. Depending on the OS, opening a connection to the display may throw an error if the tool is intended for the command line. So we try to leave all measuring of fonts and other machine relevant data until the app calls `show()`. This works generally very well, because font size commonly don't need to be known until a widget is shown or drawn. But as we see here, this is not always the case and can not always be expected from the user.

    I think too, IIRC, the font system initialization overhead is significant enough on some
    platforms that it should be delayed until absolutely necessary. Esp. so that in FLTK applications
    that don't even draw any text (pure graphics, like a speedometer on embedded hardware)

    the overhead can be avoided.

    Ugh, fixing omissions in bold to my above paragraph that I musta written while still waking up..

Paul Hahn

unread,
Jan 21, 2023, 3:00:52 PM1/21/23
to fltk.general
On Saturday, January 21, 2023 at 12:01:05 PM UTC-6 er...@seriss.com wrote:

    I think the OP's problem (which he's since corrected) is probably one of assuming
    a font had already been set, as I *think* what he's saying is he called the getter
    version of fl_font(), e.g. "fl_font(void)", without having first called fl_font(face,size) to set it,
    which probably would have yielded "undefined behavior".

Yes that is my case.


    It's certainly a valid use (and documented) to call fl_font() outside of draw(),
    such as to measure text with fl_measure() during widget construction, before graphics
    has been initialized. I'm guessing fl_font(face,size) checks if graphics has not yet been
    initialized, and initializes it.. but fl_font(void) does not (and perhaps shouldn't)

Yes exactly. My code was calling fl_font(void) without ever calling fl_font(face,size) at all, assuming that the font (and size) were initialized to some reliable "default" within FLTK (i.e., in the Fl_Window class constructor). Again, this happened when my text-oriented class was instantiated as a member of my class derived from Fl_Window. That text-oriented class calls fl_font() to set up sizes of things - again, assuming a default font + size is good.

From now on, to be rigorous, I will no longer assume there is such a thing as "default" font + size in FLTK, and that I must initialize it.

However, at least in my case, if the Fl_Window class constructor had indeed initialized all of this to some kind of defaults (including opening the display?), my code would have continued to sail smoothly on. But I understand that if opening the display fails in the constructor, about the only option is to throw an exception for the sake of the programmer who can catch it if desired.

On the other hand, maybe some other toolkits (Qt?) take care of this kind of initialization issue in a global initialization routine that programmers are required to call at the start? Like as with Fl::lock() in FLTK when we need to use MT and locks. Or, as it now appears, fl_open_display(), which might essentially fill that role now in FLTK, so calling it at the start of their program is what everyone should do as boilerplate.

Albrecht Schlosser

unread,
Jan 21, 2023, 8:39:31 PM1/21/23
to fltkg...@googlegroups.com
On 1/21/23 21:00 Paul Hahn wrote:

On Saturday, January 21, 2023 at 12:01:05 PM UTC-6 er...@seriss.com wrote:

    I think the OP's problem (which he's since corrected) is probably one of assuming
    a font had already been set, as I *think* what he's saying is he called the getter
    version of fl_font(), e.g. "fl_font(void)", without having first called fl_font(face,size) to set it,
    which probably would have yielded "undefined behavior".

Yes that is my case.

This has always been wrong, because measuring text w/o explicitly setting the font would access undefined font data. An FLTK convention is to use a font after setting it (which is fast if it has been done at least once before) and leaving the font as-is. Hence even during runtime you must always set the font you want to work with because you would otherwise use the font used before which could for instance be a bold italic 36 pix font.


    It's certainly a valid use (and documented) to call fl_font() outside of draw(),
    such as to measure text with fl_measure() during widget construction, before graphics
    has been initialized. I'm guessing fl_font(face,size) checks if graphics has not yet been
    initialized, and initializes it.. but fl_font(void) does not (and perhaps shouldn't)

Yes exactly. My code was calling fl_font(void) without ever calling fl_font(face,size) at all, assuming that the font (and size) were initialized to some reliable "default" within FLTK (i.e., in the Fl_Window class constructor). Again, this happened when my text-oriented class was instantiated as a member of my class derived from Fl_Window. That text-oriented class calls fl_font() to set up sizes of things - again, assuming a default font + size is good.

From now on, to be rigorous, I will no longer assume there is such a thing as "default" font + size in FLTK, and that I must initialize it.

To be precise (sorry for nitpicking): there *is* a default font and size, but it is not initialized at program startup automatically. There are chances that your program never uses the default font, so why bother and load it?


However, at least in my case, if the Fl_Window class constructor had indeed initialized all of this to some kind of defaults (including opening the display?), my code would have continued to sail smoothly on. But I understand that if opening the display fails in the constructor, about the only option is to throw an exception for the sake of the programmer who can catch it if desired.

That said, before commit 4b945a308 (Nov 5, 2022) there was an unwanted initialization of the graphics driver in the constructor of Fl_Widget (and hence also Fl_Window) which was removed with the mentioned commit. This was necessary for the hybrid X11/Wayland FLTK platform on Unix/Linux, but this early initialization of the graphics driver had been problematic anyway.

This *may* have hidden the problem to access uninitialized font data in your program because it crashed now with the missing graphics driver initialization.


On the other hand, maybe some other toolkits (Qt?) take care of this kind of initialization issue in a global initialization routine that programmers are required to call at the start? Like as with Fl::lock() in FLTK when we need to use MT and locks. Or, as it now appears, fl_open_display(), which might essentially fill that role now in FLTK, so calling it at the start of their program is what everyone should do as boilerplate.

fl_open_display() is called internally in many places when needed, e.g. Fl_Window::show() but also Fl::font(face, size), Fl::get_system_colors() and some (many) more functions. The rule is not to call it if it's not needed (as in fluid in command mode `-c`) but if you're sure your program needs it because it's a GUI program, then it's not wrong to call it at the start of main(). Our goal is to open the display only when necessary and that's usually when Fl_Window::show(...) is called.

Paul Hahn

unread,
Jan 22, 2023, 1:27:37 AM1/22/23
to fltk.general
On Saturday, January 21, 2023 at 7:39:31 PM UTC-6 Albrecht Schlosser wrote:
On 1/21/23 21:00 Paul Hahn wrote:

That said, before commit 4b945a308 (Nov 5, 2022) there was an unwanted initialization of the graphics driver in the constructor of Fl_Widget (and hence also Fl_Window) which was removed with the mentioned commit. This was necessary for the hybrid X11/Wayland FLTK platform on Unix/Linux, but this early initialization of the graphics driver had been problematic anyway.

This *may* have hidden the problem to access uninitialized font data in your program because it crashed now with the missing graphics driver initialization.


Fair enough, but indeed it had been my (unjustified in hindsight) assumption that some kind of "default" was extant after at least instantiating an Fl_Window. By "default", I mean the FLTK obfuscation of so-called typeface font number '0' was at least available, whatever face it is. I will now adjust things in my code as necessary to avoid that assumption.

On the other hand, maybe some other toolkits (Qt?) take care of this kind of initialization issue in a global initialization routine that programmers are required to call at the start? Like as with Fl::lock() in FLTK when we need to use MT and locks. Or, as it now appears, fl_open_display(), which might essentially fill that role now in FLTK, so calling it at the start of their program is what everyone should do as boilerplate.

fl_open_display() is called internally in many places when needed, e.g. Fl_Window::show() but also Fl::font(face, size), Fl::get_system_colors() and some (many) more functions. The rule is not to call it if it's not needed (as in fluid in command mode `-c`) but if you're sure your program needs it because it's a GUI program, then it's not wrong to call it at the start of main(). Our goal is to open the display only when necessary and that's usually when Fl_Window::show(...) is called.


Yes that is a reasonable argument. Heretofore I had unthinkingly assumed all FLTK programs are GUI oriented. Thanks for clarifying that for me.

Paul Hahn

unread,
Jan 22, 2023, 1:33:13 AM1/22/23
to fltk.general
On a completely different note... For some some reason when I respond with "inline" comments to someone's message I do not always get the expected indentation or vertical bars on the LHS. No need to chastise me about my "style"; I am trying to figure out what I am doing wrong.

Greg Ercolano

unread,
Jan 22, 2023, 4:02:21 AM1/22/23
to fltkg...@googlegroups.com

On 1/21/23 22:33, Paul Hahn wrote:

On a completely different note... For some some reason when I respond with "inline" comments to someone's message I do not always get the expected indentation or vertical bars on the LHS. No need to chastise me about my "style"; I am trying to figure out what I am doing wrong.

    Are you using the google web interface to the group?
    If so that's probably the cause; the google web interface is just not very good
    at things like quoting properly.

    Best thing to do if you can is redirect the fltk group to your email,
    set up a mail filter to move all fltk messages to a folder separate from your mailbox,
    and use that to read and reply.

    I think most of us use the email interface read and reply. That seems to handle
    everything better.


Reply all
Reply to author
Forward
0 new messages