gtk-rs/gtk

FileChooserNative memory management issue

YaLTeR opened this issue · 4 comments

Causes crashes on Flatpak and nothing happening on the host.

I believe it's dropped prematurely, see e.g. the demo code, the object is not unreffed after show().

use gio::prelude::*;
use gtk::prelude::*;

use std::env::args;

fn build_ui(application: &gtk::Application) {
    let window = gtk::ApplicationWindow::new(application);

    window.set_title("First GTK+ Program");
    window.set_border_width(10);
    window.set_position(gtk::WindowPosition::Center);
    window.set_default_size(350, 70);

    let button = gtk::Button::with_label("Click me!");

    button.connect_clicked(|_| {
        let file_chooser = gtk::FileChooserNativeBuilder::new()
            .action(gtk::FileChooserAction::Open)
            .title("Open something")
            .build();

        file_chooser.connect_response(move |file_chooser, response| {
            eprintln!("{:?}", response);

            file_chooser.destroy();
        });

        file_chooser.show();

        // Uncomment to make it behave properly.
        // use glib::translate::*;
        // let _ = file_chooser.as_object_ref().to_glib_full();
    });

    window.add(&button);

    window.show_all();
}

fn main() {
    let application =
        gtk::Application::new(Some("com.github.gtk-rs.examples.basic"), Default::default())
            .expect("Initialization failed...");

    application.connect_activate(|app| {
        build_ui(app);
    });

    application.run(&args().collect::<Vec<_>>());
}

Causes crashes on Flatpak

Can you provide a backtrace of the crash (with debug symbols)? This really shouldn't crash and doesn't here, also doesn't give any valgrind warnings.

I believe it's dropped prematurely

Yes in your code above the file_chooser is dropped right at the end of the clicked signal handler. You probably want to keep it alive a bit longer until the user closes it in one way or another.

Why this behaves differently than other dialogs is not clear to me though. Other dialogs have their window owned by GTK and stay alive until they're explicitly destroyed.

Can you provide a backtrace of the crash (with debug symbols)?

I could if it didn't also crash gdb itself when trying to do a backtrace... 😄 (I reported that here)

Here's as far as I can go before the gdb crash:

#0  0x00007f8482f86615 in gtk_widget_get_display (widget=0x3500353500353537) at gtkwidget.c:11005
11005	  g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL);

#1  0x00007f8482fa8843 in gtk_window_unexport_handle (window=0x3500353500353537) at gtkwindow.c:13000
13000	  if (GDK_IS_WAYLAND_DISPLAY (gtk_widget_get_display (GTK_WIDGET (window))))

#2  0x00007f8482dcc24f in filechooser_portal_data_free (data=data@entry=0x55da0bcd5050) at gtkfilechoosernativeportal.c:83
83	    gtk_window_unexport_handle (data->exported_window);

#3  0x00007f8482dcc9d4 in response_cb (connection=<optimized out>, sender_name=<optimized out>, object_path=<optimized out>, interface_name=<optimized out>, signal_name=<optimized out>, parameters=<optimized out>, user_data=0x55da0b966820) at gtkfilechoosernativeportal.c:175
175	  filechooser_portal_data_free (data);

#4  0x00007f848285a88f in emit_signal_instance_in_idle_cb (data=0x7f8474019950) at ../gio/gdbusconnection.c:3777
3777	    signal_instance->subscriber->callback (signal_instance->connection,

#5  0x00007f8482614c0e in g_main_dispatch (context=0x55da0b9108c0) at ../glib/gmain.c:3309
3309	          need_destroy = !(* dispatch) (source, callback, user_data);

#6  g_main_context_dispatch (context=context@entry=0x55da0b9108c0) at ../glib/gmain.c:3974
3974	      g_main_dispatch (context);

#7  0x00007f8482614fc0 in g_main_context_iterate (context=context@entry=0x55da0b9108c0, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at ../glib/gmain.c:4047
4047	    g_main_context_dispatch (context);

#8  0x00007f8482615063 in g_main_context_iteration (context=context@entry=0x55da0b9108c0, may_block=may_block@entry=1) at ../glib/gmain.c:4108
4108	  retval = g_main_context_iterate (context, may_block, TRUE, G_THREAD_SELF);

As discussed on IRC, the crash looks like a bug in the native file chooser implementation. It accesses an already freed pointer if the dialog is freed too fast, like here.

The issue that the dialog disappears immediately looks like an API ugliness in GTK and should be reported there to find out what the best way would be to keep the dialog alive long enough.