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 348953 - invalid call of free() in glib when expanding or collapsing a tree
invalid call of free() in glib when expanding or collapsing a tree
Status: VERIFIED NOTGNOME
Product: glib
Classification: Platform
Component: gobject
2.12.x
Other All
: Normal critical
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2006-07-27 16:44 UTC by Björn Martensen
Modified: 2006-07-28 20:43 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Björn Martensen 2006-07-27 16:44:25 UTC
Steps to reproduce:
1. 
2. 
3. 


Stack trace:
(gdb) bt
  • #0 __kernel_vsyscall
  • #1 raise
    from /lib/libc.so.6
  • #2 abort
    from /lib/libc.so.6
  • #3 malloc_printerr
    from /lib/libc.so.6
  • #4 free
    from /lib/libc.so.6
  • #5 g_free
    from /usr/lib/libglib-2.0.so.0
  • #6 g_slice_free1
    from /usr/lib/libglib-2.0.so.0
  • #7 thunar_vfs_monitor_remove
    from /opt/xfce4/lib/libthunar-vfs-1.so.2
  • #8 thunar_folder_finalize
    at thunar-folder.c line 247
  • #9 g_object_unref
    from /usr/lib/libgobject-2.0.so.0
  • #10 thunar_tree_model_item_reset
    at thunar-tree-model.c line 1229
  • #11 thunar_tree_model_node_traverse_free
    at thunar-tree-model.c line 1210
  • #12 g_node_traverse_post_order
    from /usr/lib/libglib-2.0.so.0
  • #13 g_node_traverse_post_order
    from /usr/lib/libglib-2.0.so.0
  • #14 g_node_traverse_post_order
    from /usr/lib/libglib-2.0.so.0
  • #15 g_node_traverse
    from /usr/lib/libglib-2.0.so.0
  • #16 thunar_tree_model_finalize
    at thunar-tree-model.c line 360
  • #17 g_object_unref
    from /usr/lib/libgobject-2.0.so.0
  • #18 thunar_tree_view_finalize
    at thunar-tree-view.c line 469
  • #19 g_object_unref
    from /usr/lib/libgobject-2.0.so.0
  • #20 g_object_run_dispose
    from /usr/lib/libgobject-2.0.so.0
  • #21 gtk_object_destroy
    from /usr/lib/libgtk-x11-2.0.so.0
  • #22 gtk_widget_destroy
    from /usr/lib/libgtk-x11-2.0.so.0
  • #23 gtk_bin_forall
    from /usr/lib/libgtk-x11-2.0.so.0
  • #24 gtk_scrolled_window_forall
    from /usr/lib/libgtk-x11-2.0.so.0
  • #25 gtk_container_foreach
    from /usr/lib/libgtk-x11-2.0.so.0
  • #26 gtk_container_destroy
    from /usr/lib/libgtk-x11-2.0.so.0
  • #27 gtk_scrolled_window_destroy
    from /usr/lib/libgtk-x11-2.0.so.0
  • #28 g_cclosure_marshal_VOID__VOID
    from /usr/lib/libgobject-2.0.so.0
  • #29 g_type_class_meta_marshal
    from /usr/lib/libgobject-2.0.so.0
  • #30 g_closure_invoke
    from /usr/lib/libgobject-2.0.so.0
  • #31 signal_emit_unlocked_R
    from /usr/lib/libgobject-2.0.so.0
  • #32 g_signal_emit_valist
    from /usr/lib/libgobject-2.0.so.0
  • #33 g_signal_emit
    from /usr/lib/libgobject-2.0.so.0
  • #34 gtk_object_dispose
    from /usr/lib/libgtk-x11-2.0.so.0
  • #35 gtk_widget_dispose
    from /usr/lib/libgtk-x11-2.0.so.0
  • #36 g_object_run_dispose
    from /usr/lib/libgobject-2.0.so.0
  • #37 gtk_object_destroy
    from /usr/lib/libgtk-x11-2.0.so.0
  • #38 gtk_widget_destroy
    from /usr/lib/libgtk-x11-2.0.so.0
  • #39 gtk_paned_forall
    from /usr/lib/libgtk-x11-2.0.so.0
  • #40 gtk_container_foreach
    from /usr/lib/libgtk-x11-2.0.so.0
  • #41 gtk_container_destroy
    from /usr/lib/libgtk-x11-2.0.so.0
  • #42 g_cclosure_marshal_VOID__VOID
    from /usr/lib/libgobject-2.0.so.0
  • #43 g_type_class_meta_marshal
    from /usr/lib/libgobject-2.0.so.0
  • #44 g_closure_invoke
    from /usr/lib/libgobject-2.0.so.0
  • #45 signal_emit_unlocked_R
    from /usr/lib/libgobject-2.0.so.0
  • #46 g_signal_emit_valist
    from /usr/lib/libgobject-2.0.so.0
  • #47 g_signal_emit
    from /usr/lib/libgobject-2.0.so.0
  • #48 gtk_object_dispose
    from /usr/lib/libgtk-x11-2.0.so.0
  • #49 gtk_widget_dispose
    from /usr/lib/libgtk-x11-2.0.so.0
  • #50 g_object_run_dispose
    from /usr/lib/libgobject-2.0.so.0
  • #51 gtk_object_destroy
    from /usr/lib/libgtk-x11-2.0.so.0
  • #52 gtk_widget_destroy
    from /usr/lib/libgtk-x11-2.0.so.0
  • #53 gtk_table_forall
    from /usr/lib/libgtk-x11-2.0.so.0
  • #54 gtk_container_foreach
    from /usr/lib/libgtk-x11-2.0.so.0
  • #55 gtk_container_destroy
    from /usr/lib/libgtk-x11-2.0.so.0
  • #56 g_cclosure_marshal_VOID__VOID
  • #57 g_type_class_meta_marshal
    from /usr/lib/libgobject-2.0.so.0
  • #58 g_closure_invoke
    from /usr/lib/libgobject-2.0.so.0
  • #59 signal_emit_unlocked_R
    from /usr/lib/libgobject-2.0.so.0
  • #60 g_signal_emit_valist
    from /usr/lib/libgobject-2.0.so.0
  • #61 g_signal_emit
    from /usr/lib/libgobject-2.0.so.0
  • #62 gtk_object_dispose
    from /usr/lib/libgtk-x11-2.0.so.0
  • #63 gtk_widget_dispose
    from /usr/lib/libgtk-x11-2.0.so.0
  • #64 g_object_run_dispose
    from /usr/lib/libgobject-2.0.so.0
  • #65 gtk_object_destroy
    from /usr/lib/libgtk-x11-2.0.so.0
  • #66 gtk_widget_destroy
    from /usr/lib/libgtk-x11-2.0.so.0
  • #67 gtk_bin_forall
    from /usr/lib/libgtk-x11-2.0.so.0
  • #68 gtk_container_foreach
    from /usr/lib/libgtk-x11-2.0.so.0
  • #69 gtk_container_destroy
    from /usr/lib/libgtk-x11-2.0.so.0
  • #70 gtk_window_destroy
    from /usr/lib/libgtk-x11-2.0.so.0
  • #71 g_cclosure_marshal_VOID__VOID
    from /usr/lib/libgobject-2.0.so.0
  • #72 g_type_class_meta_marshal
    from /usr/lib/libgobject-2.0.so.0
  • #73 g_closure_invoke
    from /usr/lib/libgobject-2.0.so.0
  • #74 signal_emit_unlocked_R
    from /usr/lib/libgobject-2.0.so.0
  • #75 g_signal_emit_valist
    from /usr/lib/libgobject-2.0.so.0
  • #76 g_signal_emit
    from /usr/lib/libgobject-2.0.so.0
  • #77 gtk_object_dispose
    from /usr/lib/libgtk-x11-2.0.so.0
  • #78 gtk_widget_dispose
    from /usr/lib/libgtk-x11-2.0.so.0
  • #79 gtk_window_dispose
    from /usr/lib/libgtk-x11-2.0.so.0
  • #80 g_object_run_dispose
    from /usr/lib/libgobject-2.0.so.0
  • #81 gtk_object_destroy
    from /usr/lib/libgtk-x11-2.0.so.0
  • #82 gtk_widget_destroy
    from /usr/lib/libgtk-x11-2.0.so.0
  • #83 gtk_main_do_event
    from /usr/lib/libgtk-x11-2.0.so.0
  • #84 gdk_event_dispatch
    from /usr/lib/libgdk-x11-2.0.so.0
  • #85 g_main_context_dispatch
    from /usr/lib/libglib-2.0.so.0
  • #86 g_main_context_iterate
    from /usr/lib/libglib-2.0.so.0
  • #87 g_main_loop_run
    from /usr/lib/libglib-2.0.so.0
  • #88 gtk_main
    from /usr/lib/libgtk-x11-2.0.so.0
  • #89 main
    at main.c line 239

Other information:
When I expand the treeview in thunar's sidepane (curent svn) it segfaults due to invalid calls of free().
Benny said this is not a thunar problem as those crashes occur also in versions without explicit usage of g_slice but only the use of gtk. see http://foo-projects.org/pipermail/thunar-dev/2006-July/003150.html

I hope g_object was the right place to put this in. I wasn't sure..
Comment 1 Owen Taylor 2006-07-27 18:31:49 UTC
A crash like this is basically *ALWAYS* a sign of memory corruptions elsewhere
in the applicatin. Please go and tell Benny"to stop telling people to report
things like this here :-)

Comment 2 Chris Wilson 2006-07-27 20:45:18 UTC
Indeed, plenty of valgrind errors to look at first. In particular, I'd recommend:
==5934== Invalid read of size 4
==5934==    at 0x80AF283: thunar_tree_model_unref_node (thunar-tree-model.c:796)
==5934==    by 0x4294919: gtk_tree_model_unref_node (gtktreemodel.c:1363)
==5934==    by 0x4297424: gtk_tree_model_filter_real_unref_node (gtktreemodelfil
ter.c:2612)
==5934==    by 0x42974CC: gtk_tree_model_filter_free_level (gtktreemodelfilter.c
:618)
==5934==    by 0x429ACA8: gtk_tree_model_filter_row_deleted (gtktreemodelfilter.
c:1792)
==5934==    by 0x4490E38: g_cclosure_marshal_VOID__BOXED (gmarshal.c:566)
==5934==    by 0x4483FFA: g_closure_invoke (gclosure.c:490)
==5934==    by 0x4494822: signal_emit_unlocked_R (gsignal.c:2438)
==5934==    by 0x4495D46: g_signal_emit_valist (gsignal.c:2197)
==5934==    by 0x4495F08: g_signal_emit (gsignal.c:2241)
==5934==    by 0x4294634: gtk_tree_model_row_deleted (gtktreemodel.c:1528)
==5934==    by 0x80B10E6: thunar_tree_model_item_notify_loading (thunar-tree-mod
el.c:1491)
==5934==  Address 0x50A6190 is 0 bytes inside a block of size 20 free'd
==5934==    at 0x4004FEA: free (vg_replace_malloc.c:233)
==5934==    by 0x44E62C0: g_free (gmem.c:187)
==5934==    by 0x44F5D25: g_slice_free1 (gslice.c:829)
==5934==    by 0x44E96F0: g_nodes_free (gnode.c:62)
==5934==    by 0x80B10C4: thunar_tree_model_item_notify_loading (thunar-tree-mod
el.c:1487)
==5934==    by 0x4490EE8: g_cclosure_marshal_VOID__PARAM (gmarshal.c:531)
==5934==    by 0x4483FFA: g_closure_invoke (gclosure.c:490)
==5934==    by 0x4494822: signal_emit_unlocked_R (gsignal.c:2438)
==5934==    by 0x4495D46: g_signal_emit_valist (gsignal.c:2197)
==5934==    by 0x4495F08: g_signal_emit (gsignal.c:2241)
==5934==    by 0x44887B0: g_object_dispatch_properties_changed (gobject.c:568)
==5934==    by 0x4484DBE: g_object_notify_dispatcher (gobject.c:249)

stemming from this bug:
--- thunar/,thunar-tree-model.c 2006-07-27 21:40:22.000000000 +0100
+++ thunar/thunar-tree-model.c  2006-07-27 21:39:27.000000000 +0100
@@ -1483,15 +1483,15 @@
       path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
       if (G_LIKELY (path != NULL))
         {
-          /* drop the dummy from the model */
-          g_node_destroy (iter.user_data);
-
           /* notify the view */
           gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
 
           /* release the path */
           gtk_tree_path_free (path);
 
+          /* drop the dummy from the model */
+          g_node_destroy (iter.user_data);
+
           /* determine the iter to the parent node */
           iter.stamp = model->stamp;
           iter.user_data = node;
Comment 3 Björn Martensen 2006-07-27 21:04:03 UTC
Thanks a lot Chris!
Your patch worked for me.
Comment 4 Björn Martensen 2006-07-27 21:12:01 UTC
Hm, unfortunately now it crashes when I delete a folder :/
Comment 5 Benedikt Meurer 2006-07-27 22:16:26 UTC
The patch does not look right to me. According to the documentation of gtk_tree_model_row_deleted()

  Emits the "row_deleted" signal on tree_model. This should be
  called by models after a row has been removed.

the node must be unlinked/destroyed first, prior to emitting the "row-deleted" signal.
Comment 6 Björn Martensen 2006-07-27 22:23:37 UTC
I just downgraded gtk from 2.10.1 to 2.8.20 and I don't get any crashes with 2.8.* so it must be related to gtk 2.10.
Comment 7 Benedikt Meurer 2006-07-27 22:38:13 UTC
Indeed, running with GTK+ 2.10 makes it crash instantly. It seems to be GtkTreeModelFilter, which is trying to unref a node in the source model after it has been deleted. For example, changing the _row_deleted() code in ThunarTreeModel to

 GNode *child = node->children;
 g_node_unlink (child);
 memset (child, 0xaa, sizeof (*child));

 gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);

 memset (child, 0x00, sizeof (*child));
 g_node_destroy (child);

you can see it crashing trying to access the no longer valid node filled with 0xaa's:

(gdb) r
Starting program: /opt/gtk210/bin/Thunar

Program received signal SIGSEGV, Segmentation fault.

Thread 1 (LWP 100618)

  • #0 thunar_tree_model_unref_node
    at thunar-tree-model.c line 807
  • #1 gtk_tree_model_unref_node
    from /opt/gtk210/lib/libgtk-x11-2.0.so.1000
  • #2 gtk_tree_model_filter_convert_iter_to_child_iter
    from /opt/gtk210/lib/libgtk-x11-2.0.so.1000
  • #3 gtk_tree_model_filter_convert_iter_to_child_iter
    from /opt/gtk210/lib/libgtk-x11-2.0.so.1000
  • #4 gtk_tree_model_filter_clear_cache
    from /opt/gtk210/lib/libgtk-x11-2.0.so.1000
  • #5 g_cclosure_marshal_VOID__BOXED
    from /opt/gtk210/lib/libgobject-2.0.so.0
  • #6 g_closure_invoke
    from /opt/gtk210/lib/libgobject-2.0.so.0
  • #7 g_signal_has_handler_pending
    from /opt/gtk210/lib/libgobject-2.0.so.0
  • #8 g_signal_emit_valist
    from /opt/gtk210/lib/libgobject-2.0.so.0
  • #9 g_signal_emit
    from /opt/gtk210/lib/libgobject-2.0.so.0
  • #10 gtk_tree_model_row_deleted
    from /opt/gtk210/lib/libgtk-x11-2.0.so.1000
  • #11 thunar_tree_model_item_notify_loading
    at thunar-tree-model.c line 1493

where thunar-tree-model.c:1493 is the location of the gtk_tree_model_row_deleted() invokation. Maybe I'm missing something, but according to the documentation a row may not be accessed after it has been deleted from the model, and citing gtk_tree_model_unref_node() "Please note that nodes that are deleted are not unreffed" I think that this is a bug in GTK+. BTW: I just checked GtkTreeStore concerning the gtk_tree_model_row_deleted() behaviour and its the same. GtkTreeStore in 2.10 doesn't crash simply because it  doesn't implement unref_node().

BTW: The bug should be filed against GTK+ not glib.
Comment 8 Chris Wilson 2006-07-28 10:13:18 UTC
Hmm, my reading of the GtkTreeModel is that the refcount is the number of views of the row (which is not the same as the number of owners...). In this case, the GtkTreeModelFilter has an additional view onto the model and so will drop a reference when the row is removed from the filter.

However, I have to leave it to the experts for authorative comments.
Comment 9 Chris Wilson 2006-07-28 20:43:14 UTC
Just for completeness:
Index: thunar/thunar-tree-model.c
===================================================================
--- thunar/thunar-tree-model.c  (revision 22552)
+++ thunar/thunar-tree-model.c  (working copy)
@@ -1492,12 +1492,12 @@
       path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
       if (G_LIKELY (path != NULL))
         {
+          /* notify the view */
+          gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+
           /* drop the dummy from the model */
           g_node_destroy (node->children);
 
-          /* notify the view */
-          gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
-
           /* determine the iter to the parent node */
           iter.stamp = model->stamp;
           iter.user_data = node;
@@ -1573,15 +1573,15 @@
   path = gtk_tree_model_get_path (GTK_TREE_MODEL (model), &iter);
   if (G_LIKELY (path != NULL))
     {
+      /* emit a "row-deleted" */
+      gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
+
       /* release the item for the node */
       thunar_tree_model_node_traverse_free (node, user_data);
 
       /* remove the node from the tree */
       g_node_destroy (node);
 
-      /* emit a "row-deleted" */
-      gtk_tree_model_row_deleted (GTK_TREE_MODEL (model), path);
-
       /* release the path */
       gtk_tree_path_free (path);
     }