GNOME Bugzilla – Bug 463730
Hang on startup
Last modified: 2007-08-13 23:27:30 UTC
totem-2.19.6 hangs on startup, with a lot of critical errors to console: $ totem (process:16379): GLib-GObject-CRITICAL **: gtype.c:2242: initialization assertion failed, use IA__g_type_init() prior to this function (process:16379): GLib-CRITICAL **: g_once_init_leave: assertion `initialization_value != 0' failed (process:16379): GLib-GObject-CRITICAL **: gtype.c:2242: initialization assertion failed, use IA__g_type_init() prior to this function (process:16379): GLib-GObject-CRITICAL **: gtype.c:2242: initialization assertion failed, use IA__g_type_init() prior to this function (process:16379): GLib-GObject-CRITICAL **: gtype.c:2242: initialization assertion failed, use IA__g_type_init() prior to this function (process:16379): GLib-GObject-CRITICAL **: g_type_add_interface_static: assertion `G_TYPE_IS_INSTANTIATABLE (instance_type)' failed (process:16379): GLib-GObject-CRITICAL **: gtype.c:2242: initialization assertion failed, use IA__g_type_init() prior to this function (process:16379): GLib-GObject-CRITICAL **: g_type_add_interface_static: assertion `G_TYPE_IS_INSTANTIATABLE (instance_type)' failed (process:16379): GLib-GObject-CRITICAL **: gtype.c:2242: initialization assertion failed, use IA__g_type_init() prior to this function (process:16379): GLib-GObject-CRITICAL **: gtype.c:2242: initialization assertion failed, use IA__g_type_init() prior to this function (process:16379): GLib-GObject-CRITICAL **: g_type_add_interface_static: assertion `G_TYPE_IS_INSTANTIATABLE (instance_type)' failed (process:16379): GLib-GObject-CRITICAL **: gtype.c:2242: initialization assertion failed, use IA__g_type_init() prior to this function (process:16379): GLib-CRITICAL **: g_once_init_leave: assertion `initialization_value != 0' failed (process:16379): GLib-GObject-CRITICAL **: gtype.c:2242: initialization assertion failed, use IA__g_type_init() prior to this function (process:16379): GLib-GObject-CRITICAL **: gtype.c:2242: initialization assertion failed, use IA__g_type_init() prior to this function (process:16379): GLib-GObject-CRITICAL **: g_type_add_interface_static: assertion `G_TYPE_IS_INSTANTIATABLE (instance_type)' failed (process:16379): GLib-CRITICAL **: g_once_init_leave: assertion `initialization_value != 0' failed
strace shows it hanging inside futex: ... open("/usr/share/locale/locale.alias", O_RDONLY|O_LARGEFILE) = 3 fstat64(3, {st_mode=S_IFREG|0644, st_size=2586, ...}) = 0 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7f04000 read(3, "# Locale name alias data base.\n#"..., 4096) = 2586 read(3, "", 4096) = 0 close(3) = 0 munmap(0xb7f04000, 4096) = 0 geteuid32() = 500 getuid32() = 500 getegid32() = 100 getgid32() = 100 futex(0x809dfcc, FUTEX_WAIT, 1, NULL
gdb is useless: Program received signal SIGINT, Interrupt.
+ Trace 153013
Thread NaN (LWP 16428)
This is odd; line 3023 of totem.c is the opening { of main().
Ah... totem was compiled with -O3 -fno-strict-aliasing (on Gentoo); could this be an optimisation bug?
Yes; here's the disassembly of main(): Dump of assembler code for function main: 0x08062100 <main+0>: lea 0x4(%esp),%ecx 0x08062104 <main+4>: and $0xfffffff0,%esp 0x08062107 <main+7>: pushl 0xfffffffc(%ecx) 0x0806210a <main+10>: push %ebp 0x0806210b <main+11>: mov %esp,%ebp 0x0806210d <main+13>: push %edi 0x0806210e <main+14>: push %esi 0x0806210f <main+15>: push %ebx 0x08062110 <main+16>: push %ecx 0x08062111 <main+17>: sub $0x68,%esp 0x08062114 <main+20>: mov %ecx,0xffffffb4(%ebp) 0x08062117 <main+23>: movl $0x808f234,0x4(%esp) 0x0806211f <main+31>: movl $0x8090255,(%esp) 0x08062126 <main+38>: call 0x805acac <bindtextdomain@plt> 0x0806212b <main+43>: movl $0x808f246,0x4(%esp) 0x08062133 <main+51>: movl $0x8090255,(%esp) 0x0806213a <main+58>: call 0x805c41c <bind_textdomain_codeset@plt> 0x0806213f <main+63>: movl $0x8090255,(%esp) 0x08062146 <main+70>: call 0x805b93c <textdomain@plt> 0x0806214b <main+75>: call 0x8059cdc <XInitThreads@plt> 0x08062150 <main+80>: test %eax,%eax 0x08062152 <main+82>: je 0x8062ba3 <main+2723> 0x08062158 <main+88>: call 0x805a85c <gtk_window_get_type@plt> 0x0806215d <main+93>: mov %eax,0xffffffd4(%ebp) 0x08062160 <main+96>: movl $0x0,(%esp) 0x08062167 <main+103>: call 0x805b02c <g_thread_init@plt> 0x0806216c <main+108>: movl $0x808f24c,(%esp) 0x08062173 <main+115>: call 0x805c22c <g_option_context_new@plt> 0x08062178 <main+120>: mov %eax,%ebx 0x0806217a <main+122>: call 0x8075d80 <bacon_video_widget_get_option_group> 0x0806217f <main+127>: movl $0x8090255,0x8(%esp) 0x08062187 <main+135>: movl $0x8090760,0x4(%esp) 0x0806218f <main+143>: mov %eax,%esi 0x08062191 <main+145>: mov %ebx,(%esp) 0x08062194 <main+148>: call 0x805c8cc <g_option_context_add_main_entries@plt> 0x08062199 <main+153>: movl $0x8090255,0x4(%esp) 0x080621a1 <main+161>: mov %ebx,(%esp) 0x080621a4 <main+164>: call 0x805a71c <g_option_context_set_translation_domain@plt> For reference here's the corresponding source: int main (int argc, char **argv) { Totem *totem; GConfClient *gc; #ifndef HAVE_GTK_ONLY GnomeProgram *program; #else GError *error = NULL; #endif GOptionContext *context; GOptionGroup *baconoptiongroup; bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); textdomain (GETTEXT_PACKAGE); #ifdef GDK_WINDOWING_X11 if (XInitThreads () == 0) { gtk_init (&argc, &argv); g_set_application_name (_("Totem Movie Player")); totem_action_error_and_exit (_("Could not initialize the thread-safe libraries."), _("Verify your system installation. Totem will now exit."), NULL); } #endif g_thread_init (NULL); /* Handle command line arguments */ context = g_option_context_new (N_("- Play movies and songs")); baconoptiongroup = bacon_video_widget_get_option_group(); g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE); g_option_context_set_translation_domain(context, GETTEXT_PACKAGE); gtk_window_get_type() doesn't get used until way later in main(), at line 3118: totem->fs = totem_fullscreen_new (GTK_WINDOW (totem->win)); Why is gcc moving it up inside the function?
OK, using a j to skip that call to gtk_window_get_type() prevents the hang (and the critical warnings), so that's the issue; still need to find out why gcc thinks it can reorder it.
Ah - gtk_window_get_type() is marked as G_GNUC_CONST. But it's not deserving of const attribute, because it is dependent on and affects the GType system (g_type_init()). Would G_GNUC_PURE work better?
Yes, it does; but waiting on GTK+ to fix gtkwindow.h isn't going to fix totem. Perhaps an early g_type_init()?
Created attachment 93120 [details] [review] g_type_init_O3_fix.patch Yes, this works. Bit of a nasty hack though.
That clearly is either a GCC, or a GTK+/glib bug. GTK+ is supposed to initialise the type system just before parsing the options. Punting to glib. Are we supposed to init the type system beforehand, even if we use gtk_get_option_group().
Type system initialisation is supposed to, and does, occur in g_option_context_parse() or gnome_program_init() (depending on whether Totem is compiled with Gnome libs). The issue is that gcc is moving a gtk_window_get_type() call to before the type system is initialised. The problem is that GTK+ headers are abusing __attribute__((const)). I've submitted bug 463781; see also bug 446565.
Be that as it may, gcc -O3 is perhaps a bit too aggressive in breaking code that has been working for a long time.
-O2 -finline-functions -O -ftree-pre -finline-functions (-ftree-pre is Partial Redundancy Elimination, enabled at -O2.) Both of these (under gcc 4.2.0) will cause the above broken asm to be emitted. Is -finline-functions really such an aggressive optimisation?
Here's a minimal reduced testcase of totem.c: #include <glib-object.h> #include <stdlib.h> int main (int argc, char **argv) { if (argc == 0) { g_type_init (); volatile GType t = g_type_module_get_type(); g_error ("oops"); } g_type_init (); volatile GType t = g_type_module_get_type(); return 0; } n.b. g_type_module_get_type() is declared with G_GNUC_CONST.
Note the above breaks with "gcc -O2" and with "gcc -O -ftree-pre"; no -finline-functions or -O3 needed.
M'kay... that's interesting. The bug disappears if totem_action_exit() (called from within totem_action_error_and_exit()) is declared G_GNUC_NORETURN. A more elegant workaround perhaps.
Created attachment 93175 [details] [review] totem-declare-noreturn.patch
2007-08-12 Bastien Nocera <hadess@hadess.net> * src/plparse/totem-pl-parser.c: (totem_pl_parser_can_parse_from_data): Add more debug when a mime-type isn't known * src/totem.h: Add patch from Ed Catmur <ed@catmur.co.uk> to avoid hangs with specific versions of GCC and a set of optimisations (Closes: #463730) The bug still lies with GCC, IMO.
*** This bug has been marked as a duplicate of 446565 ***