GNOME Bugzilla – Bug 641196
Fix another GtkFixed regression, in gtk_fixed_forall()
Last modified: 2011-02-02 05:40:35 UTC
We can get crashes because the loop is a for() instead of a while(): the callback function can result in the current child being removed, which means the next item in the list is invalid. See for example this stack trace (hrm, pasting a stack trace with git-bz -- I have to replace leading # with something else). ~0 0xffffe424 in __kernel_vsyscall () ~1 0xb6e4108b in write () from /lib/libpthread.so.0 ~2 0xb6d1bccb in write_string (fd=2, string=0x8410900 "\n(gnome-panel:7014): Gtk-CRITICAL **: gtk_widget_destroy: assertion `GTK_IS_WIDGET (widget)' failed\n") at gmessages.c:140 ~3 0xb6d1d4a9 in g_log_default_handler (log_domain=0xb771e6cb "Gtk", log_level=G_LOG_LEVEL_CRITICAL, message=0x8412438 "gtk_widget_destroy: assertion `GTK_IS_WIDGET (widget)' failed", unused_data=0x0) at gmessages.c:998 ~4 0xb6d1c6d4 in g_logv (log_domain=0xb771e6cb "Gtk", log_level=G_LOG_LEVEL_CRITICAL, format=0xb6d980bc "%s: assertion `%s' failed", args1=0xbffaf5ec "\322*r\267\300\377q\267") at gmessages.c:527 ~5 0xb6d1c7e8 in g_log (log_domain=0xb771e6cb "Gtk", log_level=G_LOG_LEVEL_CRITICAL, format=0xb6d980bc "%s: assertion `%s' failed") at gmessages.c:577 ~6 0xb6d1c82b in g_return_if_fail_warning (log_domain=0xb771e6cb "Gtk", pretty_function=0xb7722ad2 "gtk_widget_destroy", expression=0xb771ffc0 "GTK_IS_WIDGET (widget)") at gmessages.c:586 ~7 0xb75f1cf1 in gtk_widget_destroy (widget=0x8450a90) at gtkwidget.c:3804 ~8 0xb7407b90 in gtk_fixed_forall (container=0x8174000, include_internals=0, callback=0xb75f1c66 <gtk_widget_destroy>, callback_data=0x0) at gtkfixed.c:547 ~9 0xb73ae949 in gtk_container_foreach (container=0x8174000, callback=0xb75f1c66 <gtk_widget_destroy>, callback_data=0x0) at gtkcontainer.c:1931 ~10 0xb73ad233 in gtk_container_destroy (widget=0x8174000) at gtkcontainer.c:1313 ~11 0xb6e167e7 in g_cclosure_marshal_VOID__VOID (closure=0x810fba8, return_value=0x0, n_param_values=1, param_values=0x83736b0, invocation_hint=0xbffaf80c, marshal_data=0xb73ad181) at gmarshal.c:79 ~12 0xb6dfd947 in g_type_class_meta_marshal (closure=0x810fba8, return_value=0x0, n_param_values=1, param_values=0x83736b0, invocation_hint=0xbffaf80c, marshal_data=0x4c) at gclosure.c:878 ~13 0xb6dfd636 in g_closure_invoke (closure=0x810fba8, return_value=0x0, n_param_values=1, param_values=0x83736b0, invocation_hint=0xbffaf80c) at gclosure.c:767 ~14 0xb6e16562 in signal_emit_unlocked_R (node=0x810fbf8, detail=0, instance=0x8174000, emission_return=0x0, instance_and_params=0x83736b0) at gsignal.c:3368 ~15 0xb6e15337 in g_signal_emit_valist (instance=0x8174000, signal_id=29, detail=0, var_args=0xbffaf9fc "") at gsignal.c:2983 ~16 0xb6e15623 in g_signal_emit (instance=0x8174000, signal_id=29, detail=0) at gsignal.c:3040 ~17 0xb75feb42 in gtk_widget_dispose (object=0x8174000) at gtkwidget.c:10578 ~18 0x08069dbb in panel_widget_dispose (obj=0x8174000) at panel-widget.c:1734
Created attachment 179845 [details] [review] Fix another GtkFixed regression, in gtk_fixed_forall() b3f6f67c changed the loop from while() to for() in gtk_fixed_forall(), but that's wrong since the callback can have side-effects on the list, in case the current child gets removed. And that's the case when the widget is destroyed.