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 600992 - File chooser reference counting issues
File chooser reference counting issues
Status: RESOLVED FIXED
Product: gtk+
Classification: Platform
Component: Widget: GtkFileChooser
2.19.x
Other All
: Normal critical
: ---
Assigned To: gtk-bugs
Federico Mena Quintero
: 602964 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2009-11-06 18:34 UTC by John Stebbins
Modified: 2010-03-09 05:06 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Test program to reproduce crash (2.63 KB, text/plain)
2009-11-08 20:59 UTC, John Stebbins
  Details
Simplified example code that causes segfault (2.16 KB, text/plain)
2009-11-10 19:38 UTC, John Stebbins
  Details
Proposed patch (2.03 KB, patch)
2009-11-10 23:44 UTC, David Zeuthen (not reading bugmail)
none Details | Review
another patch (3.68 KB, patch)
2009-11-11 00:33 UTC, Matthias Clasen
needs-work Details | Review
another iteration (6.46 KB, patch)
2010-03-09 04:33 UTC, Matthias Clasen
none Details | Review

Description John Stebbins 2009-11-06 18:34:49 UTC
My application (HandBrake) monitors for disc removal and insertion with GVolumeMonitor.  About every 30th time the disc is ejected, I get the collection of critical messages shown below.  About every 100th time I get a segfault.  Also below is a backtrace that shows what modules were involved in the problem.  I've seen this on Ubuntu 9.10 and Pre-fedora 12.

(ghb:20578): GLib-GObject-CRITICAL **: g_object_unref: assertion `G_IS_OBJECT (object)' failed

(ghb:20578): GLib-GObject-CRITICAL **: g_object_unref: assertion `G_IS_OBJECT (object)' failed

(ghb:20578): GLib-GObject-WARNING **: instance of invalid non-instantiatable type `(null)'

(ghb:20578): GLib-GObject-CRITICAL **: g_signal_emit_by_name: assertion `G_TYPE_CHECK_INSTANCE (instance)' failed

(ghb:20578): GLib-GObject-CRITICAL **: g_object_unref: assertion `G_IS_OBJECT (object)' failed

(ghb:20578): GLib-GObject-CRITICAL **: g_value_type_compatible: assertion `G_TYPE_IS_VALUE (src_type)' failed

(ghb:20578): GLib-GObject-WARNING **: gsignal.c:2961: invalid object type `

(ghb:20578): GLib-GObject-CRITICAL **: g_object_unref: assertion `G_IS_OBJECT (object)' failed

(ghb:20578): GLib-GObject-CRITICAL **: g_object_run_dispose: assertion `G_IS_OBJECT (object)' failed

(ghb:20578): GLib-GObject-CRITICAL **: g_object_unref: assertion `G_IS_OBJECT (object)' failed

  • #0 raise
    from /lib64/libc.so.6
  • #1 abort
    from /lib64/libc.so.6
  • #2 g_logv
    from /lib64/libglib-2.0.so.0
  • #3 g_log
    from /lib64/libglib-2.0.so.0
  • #4 g_slist_foreach
    from /lib64/libglib-2.0.so.0
  • #5 ??
    from /usr/lib64/libgtk-x11-2.0.so.0
  • #6 ??
    from /usr/lib64/libgtk-x11-2.0.so.0
  • #7 ??
    from /usr/lib64/libgtk-x11-2.0.so.0
  • #8 g_closure_invoke
    from /lib64/libgobject-2.0.so.0
  • #9 ??
    from /lib64/libgobject-2.0.so.0
  • #10 g_signal_emit_valist
    from /lib64/libgobject-2.0.so.0
  • #11 g_signal_emit
    from /lib64/libgobject-2.0.so.0
  • #12 ??
    from /usr/lib64/libgtk-x11-2.0.so.0
  • #13 g_closure_invoke
    from /lib64/libgobject-2.0.so.0
  • #14 ??
    from /lib64/libgobject-2.0.so.0
  • #15 g_signal_emit_valist
    from /lib64/libgobject-2.0.so.0
  • #16 g_signal_emit_by_name
    from /lib64/libgobject-2.0.so.0
  • #17 g_closure_invoke
    from /lib64/libgobject-2.0.so.0
  • #18 ??
    from /lib64/libgobject-2.0.so.0
  • #19 g_signal_emit_valist
    from /lib64/libgobject-2.0.so.0
  • #20 g_signal_emit_by_name
    from /lib64/libgobject-2.0.so.0
  • #21 ??
    from /usr/lib64/gio/modules/libgioremote-volume-monitor.so
  • #22 g_main_context_dispatch
    from /lib64/libglib-2.0.so.0
  • #23 ??
    from /lib64/libglib-2.0.so.0
  • #24 g_main_loop_run
    from /lib64/libglib-2.0.so.0
  • #25 gtk_main
    from /usr/lib64/libgtk-x11-2.0.so.0
  • #26 main

Comment 1 Christian Persch 2009-11-06 20:54:14 UTC
Please install debug symbols for libglib/gio/gtk+/gvfs/etc and get a backtrace from the first critical warning.
Comment 2 John Stebbins 2009-11-06 22:24:36 UTC
Your wish is my command.

  • #0 raise
    at ../nptl/sysdeps/unix/sysv/linux/raise.c line 64
  • #1 abort
    at abort.c line 92
  • #2 IA__g_logv
    at gmessages.c line 549
  • #3 IA__g_log
    at gmessages.c line 569
  • #4 IA__g_slist_foreach
    at gslist.c line 743
  • #5 get_volumes_list
    at gtkfilesystem.c line 414
  • #6 _gtk_file_system_list_volumes
    at gtkfilesystem.c line 604
  • #7 shortcuts_add_volumes
    at gtkfilechooserdefault.c line 2072
  • #8 volumes_bookmarks_changed_cb
    at gtkfilechooserdefault.c line 5513
  • #9 IA__g_closure_invoke
    at gclosure.c line 767
  • #10 signal_emit_unlocked_R
    at gsignal.c line 3247
  • #11 IA__g_signal_emit_valist
    at gsignal.c line 2980
  • #12 IA__g_signal_emit
    at gsignal.c line 3037
  • #13 volumes_changed
    at gtkfilesystem.c line 161
  • #14 IA__g_closure_invoke
    at gclosure.c line 767
  • #15 signal_emit_unlocked_R
    at gsignal.c line 3247
  • #16 IA__g_signal_emit_valist
    at gsignal.c line 2980
  • #17 IA__g_signal_emit_by_name
    at gsignal.c line 3074
  • #18 IA__g_closure_invoke
  • #19 signal_emit_unlocked_R
    at gsignal.c line 3247
  • #20 IA__g_signal_emit_valist
    at gsignal.c line 2980
  • #21 IA__g_signal_emit_by_name
    at gsignal.c line 3074
  • #22 signal_emit_in_idle_do
    at gproxyvolumemonitor.c line 498
  • #23 g_main_dispatch
    at gmain.c line 1960
  • #24 IA__g_main_context_dispatch
    at gmain.c line 2513
  • #25 g_main_context_iterate
    at gmain.c line 2591
  • #26 IA__g_main_loop_run
    at gmain.c line 2799
  • #27 IA__gtk_main
    at gtkmain.c line 1218
  • #28 main
    at /home/jstebbins/Source/HandBrake/build.debug/../gtk/src/main.c line 865

Comment 3 David Zeuthen (not reading bugmail) 2009-11-08 01:23:08 UTC
(In reply to comment #0)
> My application (HandBrake) monitors for disc removal and insertion with
> GVolumeMonitor.  About every 30th time the disc is ejected, I get the
> collection of critical messages shown below.  About every 100th time I get a
> segfault.  Also below is a backtrace that shows what modules were involved in
> the problem.  I've seen this on Ubuntu 9.10 and Pre-fedora 12.

The stack trace in comment 2 indicates this happens in the GTK+ file chooser. So either this happens when you are showing a file chooser or maybe your app is leaking one?

Are you running Nautilus or the panel when this happens? Do either of these crash? If no, then it's probably not a bug in the proxy volume monitor code (they receive the same signals from the volume monitor process). Otherwise, looks to me like the root bug is in the file chooser - probably the file chooser is forgetting to disconnect a signal on GVolumeMonitor.

If you start, say, gedit and bring up the file chooser, does that process also crash at the same time?
Comment 4 John Stebbins 2009-11-08 07:27:21 UTC
My app has a couple file chooser buttons and a file chooser dialog that is hidden when not in use.  I was not running nautilus at the time of the test.  The panel survives.  I'll try the gedit test tomorrow and get back to you on that.
Comment 5 John Stebbins 2009-11-08 20:59:05 UTC
Created attachment 147227 [details]
Test program to reproduce crash
Comment 6 John Stebbins 2009-11-08 21:00:06 UTC
I tried to reproduce with gedit, and could not.  So I created a minimal program that reproduces the problem.  Although in this case the failure seems to happen in a different place, see backtrace.  The test program is attached.

To reproduce the problem I have to:

1. Instantiate a GtkFileChooserDialog
2. monitor drive-changed events from GVolumeMonitor
3. upon drive-changed, start a thread that gets a list of drives 
   from GVolumeMonitor, then unref them in the thread.

The problem does not seem to occur if either 1 or 3 are omitted from the test.

Backtrace:
  • #0 raise
    at ../nptl/sysdeps/unix/sysv/linux/raise.c line 64
  • #1 abort
    at abort.c line 92
  • #2 IA__g_logv
    at gmessages.c line 549
  • #3 IA__g_log
    at gmessages.c line 569
  • #4 dispose_in_idle_do
    at gproxyvolumemonitor.c line 526
  • #5 g_main_dispatch
    at gmain.c line 1960
  • #6 IA__g_main_context_dispatch
    at gmain.c line 2513
  • #7 g_main_context_iterate
    at gmain.c line 2591
  • #8 IA__g_main_loop_run
    at gmain.c line 2799
  • #9 IA__gtk_dialog_run
    at gtkdialog.c line 1090
  • #10 file_chooser_idle
    at main.c line 111
  • #11 g_main_dispatch
    at gmain.c line 1960
  • #12 IA__g_main_context_dispatch
    at gmain.c line 2513
  • #13 g_main_context_iterate
    at gmain.c line 2591
  • #14 IA__g_main_loop_run
    at gmain.c line 2799
  • #15 IA__gtk_main
    at gtkmain.c line 1218
  • #16 main
    at main.c line 144

Comment 7 John Stebbins 2009-11-10 19:37:04 UTC
While fiddling around to see if I could work around this problem, I found that it is not necessary to do step 3 above on a separate thread to provoke the problem.  Just performing those operations in the drive-changed callback will trigger a segfault.  I'm attaching a simplified code example.
Comment 8 John Stebbins 2009-11-10 19:38:13 UTC
Created attachment 147401 [details]
Simplified example code that causes segfault
Comment 9 David Zeuthen (not reading bugmail) 2009-11-10 20:20:45 UTC
(In reply to comment #8)
> Created an attachment (id=147401) [details]
> Simplified example code that causes segfault

Thanks, I can easily reproduce this by plugging in / removing a SD card a couple of times. FWIW, it only happens when there's a file chooser so I think there's something wrong in that code.
Comment 10 David Zeuthen (not reading bugmail) 2009-11-10 22:16:40 UTC
Actually I can reproduce this with gedit (with a open file chooser) as well.
Comment 11 David Zeuthen (not reading bugmail) 2009-11-10 23:15:14 UTC
Reassigning to the file chooser. I just looked at the code (in the gtk-2-18 branch) together with Matthias and there's some funky ref/unref logic (or lack of) going on. And the panel and nautilus, both heavy users of the GVolumeMonitor/GDrive/GVolume/GMount code never crashes. So I'm pretty sure this is not a bug in the GVfs proxy volume monitor code

I'm also going to try this with gtk+'s master branch - Company's file chooser rewrite might fix this.

(In reply to comment #4)
> My app has a couple file chooser buttons and a file chooser dialog that is
> hidden when not in use.  I was not running nautilus at the time of the test. 
> The panel survives.  I'll try the gedit test tomorrow and get back to you on
> that.

John, one work-around that might work is to avoid having a file chooser dialog that is hidden. Just construct a new one when you need it and destroy it when you are done with it.
Comment 12 David Zeuthen (not reading bugmail) 2009-11-10 23:20:56 UTC
(In reply to comment #11)
> I'm also going to try this with gtk+'s master branch - Company's file chooser
> rewrite might fix this.

Same issue. Not surprising since 'git diff master origin/gtk-2-18 gtkfilesystem.c' is empty...
Comment 13 David Zeuthen (not reading bugmail) 2009-11-10 23:44:31 UTC
Created attachment 147433 [details] [review]
Proposed patch

Matthias asked me to try this patch - it worked for me. John, can you try it out and see if it fixes the problems on your end too? Thanks.
Comment 14 Matthias Clasen 2009-11-11 00:04:41 UTC
To point out the obvious, this patch fixes a few leaks in gtkfilesystem.c:get_volumes_list and among the calls of _gtk_file_system_get_volume_for_file.

And it probably fixes the crash by removing the _gtk_file_system_volume_free calls for the GtkFileSystemVolume pointers that we stuff in the shortcuts model.
This is necessary since most of those are 'non-allocated' pointers that we got from _gtk_file_system_list_volumes.

On the flip side, this probably introduces a small leak again because we also sometimes insert allocated volumes gotten from _gtk_file_system_get_volume_for_file (see e.g. shortcuts_add_current_folder)
Comment 15 John Stebbins 2009-11-11 00:23:21 UTC
David, regarding instantiating a new file chooser dialog when needed, that won't help because I also have a couple file chooser buttons.  File chooser buttons create their own private file chooser dialog when the button is created.

I'll give the patch a try. By the sound of it, it will do the trick.
Comment 16 Matthias Clasen 2009-11-11 00:33:54 UTC
Created attachment 147436 [details] [review]
another patch

I've since discovered more volume-related issues; here is an alternative patch.
This one make _gtk_file_system_list_volumes() return new references; most callers kinda expected that anyway...
Comment 17 John Stebbins 2009-11-11 00:57:33 UTC
I hammered away on the first patch for a while and it seemed to work fine.  Then I saw your second patch and hammered on it for a while as well.  Both seem to fix my problem.
Comment 18 Matthias Clasen 2009-11-11 01:42:06 UTC
Thanks for testing !
Comment 19 Federico Mena Quintero 2009-11-11 15:21:00 UTC
Review of attachment 147436 [details] [review]:

Except for the comment in gtkfilechooserdefault.c, everything else looks correct.  Thanks for that; debugging refcounting is always a pain in the ass.

::: pristine/gtk/gtkfilechooserdefault.c
@@ +2095,3 @@
+                {
+                  _gtk_file_system_volume_free (volume);
+                  continue;

This seems wrong.  We are in a "for (all volumes)" loop.  However, none of the functions called from that loop seem to take references to the volume.  So, all the loop's iterations should unref the volume.

It would be cleaner to just unref each volume in the loop (or in a separate g_slist_foreach()), and just let each of the called functions ref the volume if they need to keep it around.
Comment 20 Matthias Clasen 2009-11-11 15:26:05 UTC
There is no api to ref GtkFileSystemVolume objects, only the _free function :-( 
That is why I changed the list_volumes function to return new references. Which is why we need to drop the reference in the continue case. If we don't hit the continue case, we keep the reference to stuff it in the shortcuts model. It gets dropped in shortcuts_free_row_data
Comment 21 Federico Mena Quintero 2009-11-23 23:31:10 UTC
GtkFileSystemVolume is internal to GTK+, so we can easily have ref/unref functions for it without breaking the ABI.  This may make things easier to maintain in the future, rather than being extra-careful about when to free things in loops.
Comment 22 Philippe Rouquier 2010-03-02 19:42:17 UTC
*** Bug 602964 has been marked as a duplicate of this bug. ***
Comment 23 Matthias Clasen 2010-03-09 04:33:51 UTC
Created attachment 155614 [details] [review]
another iteration
Comment 24 Matthias Clasen 2010-03-09 04:34:51 UTC
This patch replaces _gtk_file_system_volume_free with _ref/_unref