2

My Gtk-rs program crashes if I want to run a gtk application multiple times.

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

static APP_ID: &'static str = "com.localserver.app";

fn build_ui(app: &gtk::Application, fallback_message: Option<&'static str>) {
    {
        let window = gtk::ApplicationWindow::new(app);
        window.set_title("App");
        window.set_position(gtk::WindowPosition::Center);
        window.set_default_size(350, 70);

        window.add(&gtk::Label::new(Some(
            fallback_message.unwrap_or("Hello world"),
        )));

        window
    }
    .show_all();
}

fn main() {
    let args = std::env::args().collect::<Vec<_>>();
    let application: gtk::Application =
        gtk::Application::new(Some(APP_ID), Default::default()).unwrap();
    application.connect_activate(|app| build_ui(&app, None));

    for n in 1 .. 4 {
        application.run(&args);
        println!("Window loaded {} times.", n);
    }
}

When ran, it goes thorough the first iteration in the for loop at the end but crashes the next time:

(dbustest_rs:9805): GLib-GIO-CRITICAL **: 19:23:51.883: g_application_parse_command_line: assertion '!application->priv->options_parsed' failed
Segmentation fault (core dumped)

What's causing this and how can I prevent it?

noconst
  • 639
  • 4
  • 15
  • Your `Some(fallback_message.unwrap_or("Hello world"))` can be written: `fallback_message.or(Some("Hello world"))` – Boiethios Sep 06 '19 at 09:51
  • This should probably be raised as an issue in gtk-rs - you should never be able to cause a segfault from within safe Rust code. Admittedly the line is a little fuzzy here since it's happening in an external library, but still! – Joe Clay Sep 06 '19 at 11:59

1 Answers1

4

The issue is a simple misunderstanding in what happens and the hierarchy of objects in GTK.

GTK's object tree starts with an Application, which you have in your case. It then has 1 or more ApplicationWindows, which are the "windows" themselves. From there, all your components live under that.

You've done this hierarchy properly - you create your ApplicationWindows under the Application as you should. However, you then decide to run() this application four times, and there is a check inside the library to see if the arguments were parsed before. As it is the same (recycled) application, they are, and it errors out.

Consider recreating Application every time; it follows the natural GTK lifecycle as well.

Sébastien Renauld
  • 19,203
  • 2
  • 46
  • 66
  • Also, [from the doc](http://gtk-rs.org/docs/gio/prelude/trait.ApplicationExtManual.html#tymethod.run): *Much like `glib::MainLoop::run`, this function will acquire the main context for the duration that the application is running.* That can only be done once. – Boiethios Sep 06 '19 at 09:58