GNOME Bugzilla – Bug 659236
GtkApplication::local_command_line() vfunc has no main loop
Last modified: 2011-09-19 12:43:33 UTC
When GApplication's local_command_line() vfunc is run there is not yet a mainloop running so we can't use various parts of the glib or GTK+ API easily. For instance, in the attached test case, we can't instantiate a GtkWindow, because gtk_window_init() fails in gtk_settings_get_for_screen(), with this warning and backtrace at that warning: (a.out:15860): Gtk-CRITICAL **: gtk_settings_get_for_screen: assertion `GDK_IS_SCREEN (screen)' failed
+ Trace 228472
Presumably this also prevents use of GFile and friends too, which could be useful when checking the validity of filepath command-line arguments. I guess this is intended, because you want to strongly discourage apps from doing much work in local_command_line(), but this concern is apparently not relevant for people using G_APPLICATION_NON_UNIQUE and it's easier to implicitly use the wrong API in languages such as C++, making it harder to debug this. In particular, this makes it impossible to encapsulate the command-line processing inside a derived GtkWindow main window class - something which feels natural with gtkmm. At the least, this should be documented. So far, this documentation http://developer.gnome.org/gio/unstable/GApplication.html says " If, after the above is done, the use count of the application is zero then the exit status is returned immediately. If the use count is non-zero then the mainloop is run until the use count falls to zero, at which point 0 is returned. " But that's a very indirect way of hinting at this issue.
Created attachment 196714 [details] test_application_localcommandline.c
Gtk should definitely not be initialised at the time that local_command_line() is run since it could very well be the case that this instance is about to exit. Instead of creating windows there, you should first register the application and then re-enter GApplication via things like g_application_open, g_application_activate and g_action_group_activate_action() in response to whatever the commandline arguments were. This will turn into requests that are either delivered to the (now-registered) local app or to the remote instance, as appropriate. Take a look at g_application_real_local_command_line() in gapplication.c to get an idea of how this should go...
btw: you point out the non-unique case as a compelling example for why you might want to do this. For that situation, you can just use 'command_line' as an approximate equivalent to local_command_line, except that everything will be initialised at that point already.
Sorry, this was an attempt to create a C test case for a problem in our C++ wrapper, but that problem has now gone away by itself, and this wasn't a correct test for it anyway. I am generally more concerned with using Gio in local_command_line(), than with creating Windows. That was just an extreme example. It seems genuinely useful for a local instance to check that a file even exists, for example, before asking a remote instance to open it.
But I will file an actual bug if I find that that is actually impossible.
Using gio should really not be a problem. The problem in local_command_line isn't that there is no mainloop (which isn't a problem at all) but simply that gtk_init() has not yet been called. That won't affect GIO (which only requires that g_type_init() has been called -- which it has).