GNOME Bugzilla – Bug 761332
Creating a GtkStyleContext crashes
Last modified: 2016-01-31 03:31:07 UTC
It used to be possible (and useful) to create and use GtkStyleContext even when there is no default screen. Something between 3.8 and 3.18 that has started crashing. See https://bugzilla.gnome.org/show_bug.cgi?id=761296#c2 for a stack trace.
how is it that there is no default screen ?
This is for ssconvert, the command-line version of Gnumeric. No gui at all. As documented, ssconvert initializes gtk+ wth g_option_context_parse and that doesn't create a default screen. * Note that there are some alternative ways to initialize GTK+: * if you are calling gtk_parse_args(), gtk_init_check(), * gtk_init_with_args() or g_option_context_parse() with * the option group returned by gtk_get_option_group(), * you don’t have to call gtk_init().
Ah right. We do have a way to initialize gtk without opening a display. Some things obviously won't work in that situation, and creating style contexts has moved from 'kinda works' to 'doesn't work'. We could either try to move it back or document the limitations better. Why do you need a style context in a gui-less commandline tool ?
> Why do you need a style context in a gui-less commandline tool ? In this case, I am creating a pdf file and need a font. I.e., I am drawing to some cairo pdf surface. (I ought to get colour and other style information too, but I don't think we actually have the code for that.)
GtkStyleContext uses the screen for querying the default values of various properties, such as the default font or the scale factor during the compute stage. I think this used to work differently back in the days as it registered the settings object as a style provider. But I had to move away from that because it broke various CSS things (example: "font-size: initial"). _gtk_style_provider_private_get_settings() is the functions used for that and would have to be audited to make sure all the code deals with it returning NULL.
Oh actually, upon glancing through the code: We are using the screen right in the init function to query the actual style provider because the CSS loading of the default theme is handled by the GtkSettings. So obviously, without a screen there's no theme and without a theme there's no CSS. And that makes a style context very useless.
> We are using the screen right in the init function [...] Indeed it does, but that is a bit of a hack. Using the properties of a random, unrelated GdkScreen (which is precisely what gtk_screen_get_default will return to you) feels quite wrong.
It's called defensive programming. And it shouldn't hurt to initialize the style context with values from the default screen because the default screen will always exist. After all, a style context without a screen is entirely useless.
I've added a comment to gdk_parse_args, and made style context creation throw an error when the display is missing.
> default screen will always exist I think you came in a little late in this bug report. See comment 2 as to why there is no default screen. > After all, a style context without a screen is entirely useless. It is *now*. (Or would be, if one could create such a style context.) But it used to be just fine and useful. (As in "we used it and we got meaningful results".) Now we just get a crash.
Well, you used it even though it spewed criticals to stderr. But it seems to have limped along well enough to not outright crash.
In 3.8 it does not spew any criticals and it provides good results. The ABI changed sometime later than that.
$> cat test.c #include <gtk/gtk.h> int main (int argc, char **argv) { GError *error = NULL; GOptionContext *context; context = g_option_context_new ("- test tree model performance"); g_option_context_add_group (context, gtk_get_option_group (FALSE)); if (!g_option_context_parse (context, &argc, &argv, &error)) { g_print ("option parsing failed: %s\n", error->message); return 1; } g_object_unref (gtk_style_context_new ()); return 0; } $> LD_PRELOAD=/usr/lib64/libgtk-3.so.0.800.9 ./test (test116:4848): Gtk-CRITICAL **: _gtk_style_cascade_get_for_screen: assertion 'GDK_IS_SCREEN (screen)' failed
I may be wrong about when things changed. Sorry about that, I should have double checked. Here's the same program running with gtk+ 3.0.0: $ LD_LIBRARY_PATH=$HOME/testing/lib ./test [nothing] (I also added print statements around the interesting part and it really does get there.)