Forking processes and Gtk2

I made a change recently on the gjay program. gjay is a gtk program that basically analyzes your music and makes playlists. There is a gui frontend and a analyzer back-end and they communicate through a pipe.

One really useful debugging option gtk has is to make warnings fatal, so when gtk finds one it crashes at that point and you can use gdb to trap it. The flag is –g-fatal-warnings.  I have been updating gjay and initially it didn’t have this option, so I needed to add the gtk options, which is a simple one-liner.

But then gjay gave some odd errors about XCB. Often, but not every time gjay started on stderr the following cryptic messages appear:

[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
forktest: ../../src/xcb_io.c:274: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.

OK, so part of my init sequence was unhappy. The odd thing was it only appeared when I added the gtk options.  I narrowed it down with some test code which displayed the error but stripped all the other parts out.

  1. #include <gtk/gtk.h>
  2.  
  3. int main(int argc, char *argv[])
  4. {
  5.     GOptionContext *context;
  6.     GError *error;
  7.     pid_t pid;
  8.     GtkWidget *win;
  9.  
  10.     context = g_option_context_new("My test");
  11.     g_option_context_add_group (context, gtk_get_option_group (TRUE));
  12.     error = NULL;
  13.     if (!g_option_context_parse(context, &argc, &argv, &error))
  14.         return 1;
  15.     pid = fork();
  16.     if (pid < 0) 
  17.         return 1;
  18.     if (pid == 0) { //child
  19.         GMainLoop *loop;
  20.  
  21.         loop = g_main_new(FALSE);
  22.         g_main_run(loop);
  23.         return 0;
  24.     } else { // parent
  25.         if (gtk_init_check(&argc, &argv) == FALSE)
  26.             return 1;
  27.         win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
  28.         gtk_widget_show(win);
  29.         gtk_main();
  30.     }
  31.     return 0;
  32. }

What we got going on here is a simple gtk program.  Line 11 with the gtk_get_option_group() was the line I added. The problem is that the child process is not quite setup and when the parent goes into gtk_main then you get those xcb errors.

The options need to be parsed before the fork, because one of the options is to not fork (it just runs the child code directly and uses stdout with no GUI).

Gjay is obviously a lot more complex than this, but follows the same pattern. There is the front-end looping through gtk_main and the back-end looping on g_main_run. The backend needs to use glib not gtk as there is a non-gui option which can be used.

The solution is actually (but not obviously to me) in the documentation for gtk_get_option_group. The parameter for that function “whether to open the default display when parsing the commandline arguments”.

Changing the TRUE to FALSE on line 11 stops XCB from complaining! The screen still appears fine but not more strange XCB messages.

One thought on “Forking processes and Gtk2

Comments are closed.