community/gnome-control-center: Segfault during startup on aarch64
As the title says, with GTK 4.8.0 gnome-control-center segfaults during startup on aarch64 (e.g. Pinephone). This issue is a summary of a collective effort on postmarketOS chat (@Arnavion, Piraty, Newbyte, and myself). Note that pmOS used 4.6.6 before the 4.8.0 update. The crash isn't reproducible on armv7, I don't know about other architectures.
The log during the crash doesn't say much, but hints at a NULL pointer:
(gnome-control-center:9814): GLib-GObject-WARNING **: 18:38:36.337: invalid class cast from (NULL) pointer to 'GObject'
Segmentation fault
Backtrace from GDB (with gtk4.0-dbg
and glib-dbg
installed):
#0 0x0000fffff75aa014 in gdk_texture_dispose (object=0xfffff163b800)
at ../gdk/gdktexture.c:287
#1 0x0000fffff7d2c710 in g_object_unref (_object=<optimized out>)
at ../gobject/gobject.c:3636
#2 g_object_unref (_object=0xfffff163b800) at ../gobject/gobject.c:3553
#3 0x0000fffff7377e74 in gtk_icon_paintable_finalize (object=0xfffff176a160)
at ../gtk/gtkicontheme.c:3532
#4 0x0000fffff7d2c7d0 in g_object_unref (_object=<optimized out>)
at ../gobject/gobject.c:3678
#5 g_object_unref (_object=0xfffff176a160) at ../gobject/gobject.c:3553
#6 0x0000fffff75053c8 in gtk_icon_helper_invalidate (self=0xfffff1ff5680)
at ../gtk/gtkiconhelper.c:338
#7 0x0000fffff73840e8 in gtk_image_system_setting_changed (
widget=0xfffff1f9dc50, setting=GTK_SYSTEM_SETTING_ICON_THEME)
at ../gtk/gtkimage.c:1184
#8 0x0000fffff74b8590 in gtk_widget_real_system_setting_changed (
widget=<optimized out>, setting=GTK_SYSTEM_SETTING_ICON_THEME)
at ../gtk/gtkwidget.c:4976
#9 0x0000fffff74b8590 in gtk_widget_real_system_setting_changed (
widget=<optimized out>, setting=GTK_SYSTEM_SETTING_ICON_THEME)
at ../gtk/gtkwidget.c:4976
#10 0x0000fffff74b8590 in gtk_widget_real_system_setting_changed (
widget=<optimized out>, setting=GTK_SYSTEM_SETTING_ICON_THEME)
at ../gtk/gtkwidget.c:4976
#11 0x0000fffff74b8590 in gtk_widget_real_system_setting_changed (
widget=<optimized out>, setting=GTK_SYSTEM_SETTING_ICON_THEME)
at ../gtk/gtkwidget.c:4976
#12 0x0000fffff74b8590 in gtk_widget_real_system_setting_changed (
widget=<optimized out>, setting=GTK_SYSTEM_SETTING_ICON_THEME)
at ../gtk/gtkwidget.c:4976
#13 0x0000fffff74b8590 in gtk_widget_real_system_setting_changed (
widget=<optimized out>, setting=GTK_SYSTEM_SETTING_ICON_THEME)
at ../gtk/gtkwidget.c:4976
#14 0x0000fffff74b8590 in gtk_widget_real_system_setting_changed (
widget=<optimized out>, setting=GTK_SYSTEM_SETTING_ICON_THEME)
at ../gtk/gtkwidget.c:4976
#15 0x0000fffff74b8590 in gtk_widget_real_system_setting_changed (
widget=<optimized out>, setting=GTK_SYSTEM_SETTING_ICON_THEME)
at ../gtk/gtkwidget.c:4976
#16 0x0000fffff74b8590 in gtk_widget_real_system_setting_changed (
widget=<optimized out>, setting=GTK_SYSTEM_SETTING_ICON_THEME)
at ../gtk/gtkwidget.c:4976
#17 0x0000fffff74b8590 in gtk_widget_real_system_setting_changed (
widget=<optimized out>, setting=GTK_SYSTEM_SETTING_ICON_THEME)
at ../gtk/gtkwidget.c:4976
#18 0x0000fffff74be380 in gtk_system_setting_changed (display=0xfffff2bf40c0,
setting=GTK_SYSTEM_SETTING_ICON_THEME) at ../gtk/gtkwidget.c:10684
#19 0x0000fffff7377a20 in theme_changed_idle__mainthread_unlocked (
user_data=0xfffff208c760) at ../gtk/gtkicontheme.c:1318
#20 0x0000fffff7c350e8 in g_main_dispatch (context=0xfffff7995f10)
at ../glib/gmain.c:3417
#21 g_main_context_dispatch (context=0xfffff7995f10) at ../glib/gmain.c:4135
#22 0x0000fffff7c35348 in g_main_context_iterate (
context=context@entry=0xfffff7995f10, block=block@entry=1,
dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/gmain.c:4211
#23 0x0000fffff7c35430 in g_main_context_iteration (
context=context@entry=0xfffff7995f10, may_block=may_block@entry=1)
#24 0x0000fffff7e59d50 in g_application_run (application=0xfffff3235110,
argc=<optimized out>, argv=0xfffffffff7b8) at ../gio/gapplication.c:2569
#25 0x0000aaaaaaafe2ec in main ()
The icon being processed in gtk_icon_paintable_finalize
varies, but it's always in there, presumably the first icon to be processed. I'll quote the chat for the rest to make sure I don't leave out anything important:
<Arnavion> Weird, that line is G_OBJECT_CLASS (gdk_texture_parent_class)->dispose (object) where G_OBJECT_CLASS eventually expands to a call to g_type_check_class_cast(gdk_texture_parent_class), so given the bt that would indicate gdk_texture_parent_class is NULL, but gdb says it's a valid GObjectClass
<Arnavion> Hah, adding a breakpoint on gdk_texture_dispose reveals that a) gdk_texture_parent_class is not NULL, and b) now g-c-c comes up
<Arnavion> So there must be a race between threads for when gdk_texture_parent_class gets initialized
<airtower> Okay, that's fascinating! :D
<Arnavion> airtower, Piraty: Can you try it too?
break gdk_texture_dispose
, wait for it to get hit once, and then keepc
ing it. It'll break six or seven times and then g-c-c should come up<Piraty> yep, there it is
<airtower> Yep, works for me too.
<Arnavion> I assume gdk_texture_parent_class gets defined by gobject macro magic because I can't find any other occurence of it, so I don't know how it's initialized...
<Arnavion> airtower: Piraty: Unfortunately all my attempts to catch the situation where that global is NULL don't work. Any breakpoint that's complicated enough to only stop when that global is NULL or $x0 register is NULL introduces enough slowness that the race doesn't happen