After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 641196 - Fix another GtkFixed regression, in gtk_fixed_forall()
Fix another GtkFixed regression, in gtk_fixed_forall()
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Widget: Other
unspecified
Other All
: Normal normal
: ---
Assigned To: gtk-bugs
gtk-bugs
Depends on:
Blocks:
 
 
Reported: 2011-02-01 22:34 UTC by Vincent Untz
Modified: 2011-02-02 05:40 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Fix another GtkFixed regression, in gtk_fixed_forall() (1.05 KB, patch)
2011-02-01 22:34 UTC, Vincent Untz
none Details | Review

Description Vincent Untz 2011-02-01 22:34:11 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
Comment 1 Vincent Untz 2011-02-01 22:34:14 UTC
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.