strange D-Bus interactions with gtk_dialog_run

Gnaural gnaural at users.sourceforge.net
Thu Nov 29 08:38:49 PST 2007


OK, after a few emails with folks on the
gtk-app-devel-list, I think I understand some more
about gtk_file_chooser_dialog_new. And while it is a
weird function (creating lots of threads and
apparently sending SIGALRMs that plague sleep()'s in
other threads), it doesn't seem to be buggy per-se. So
I'm back to thinking the bug is either in D-Bus or in
how I'm implementing my server.

I've taken some time to write the bare-minimum
cut-and-past "main.c" program (below) that will always
demonstrate the bad behavior. I also formatted it to
fit in the post better than my last example, tested
the compile line, and gave a dbus-send line to contact
it. All that is in the commented section at top.

What I see when I run it ("HelloThreadBreaker" in
"broken-mode") is inconsistent, but always bad. The
usual scenario is this:

The main thread blocks at gtk_file_chooser_dialog_new
without showing the dialog. But if I send a few method
calls to the dbus server, the
gtk_file_chooser_dialog_new sometimes will show, but
normally doesn't respond to any input (or repaint
itself). If I send some more dbus method calls, or
wait a very long time, the dialog MAY come to life
long enough for me to naturally end it, at which point
the main thread moves on to gtk_main() -- BUT (most
problematic) the D-Bus server thread will from then-on
receive lots of unrecognized signal/method calls
accompanying each legit one I send it from dbus-send,
and occasionally also a few null-message calls that I
never see when running it with SHOW_BROKEN_EXAMPLE
undefined.

Indeed, to see an example of everything I need from
D-Bus, run it with SHOW_BROKEN_EXAMPLE undefined.

Hopefully the weirdness is just artifact how
implementing my server. Thanks in advance for any info
you can provide.

/////////////////////////////////////////
/*
Test D-Bus server to demonstrate bad
gtk_file_chooser_dialog_new/GThread/D-Bus 
interaction. Compile with: 
gcc main.c -o HelloThreadBreaker \
 `pkg-config --cflags --libs gtk+-2.0 \
 gthread-2.0 dbus-1`

To contact this server: 
dbus-send --session --type=method_call \
 --dest=org.gnaural.Server \
 /org/gnaural/object \
 org.gnaural.interface.Hello

For un-broken example, comment-out
the #define SHOW_BROKEN_EXAMPLE line:
*/
#define SHOW_BROKEN_EXAMPLE

#include <gtk/gtk.h>
#include <dbus/dbus.h>

void process_msg(
 DBusMessage * msg)
{
 if (NULL != msg) {
  if (dbus_message_is_method_call(msg,
    "org.gnaural.interface", "Hello"))
   g_print("Hello method called\n");
  else
   g_print("Got something, type: %d\n",
    dbus_message_get_type(msg));
  dbus_message_unref(msg);
 } else
  g_print("msg == NULL\n");
}

void *wait_for_dbus_messages(
 void *args)
{
 DBusConnection *conn;
 DBusError err;

 g_print("D-Bus thread starting\n");
 dbus_error_init(&err);
 conn =
  dbus_bus_get(DBUS_BUS_SESSION, &err);
 if (dbus_error_is_set(&err)) {
  fprintf(stderr,
   "Connection Error (%s)\n",
   err.message);
  dbus_error_free(&err);
 }
 dbus_bus_request_name(conn,
  "org.gnaural.Server",
  DBUS_NAME_FLAG_REPLACE_EXISTING,
  &err);
 while (1) {
  while (DBUS_DISPATCH_DATA_REMAINS ==
   dbus_connection_get_dispatch_status
   (conn)) {
   process_msg
    (dbus_connection_pop_message(conn));
  }
  dbus_connection_read_write(conn, -1);
 }

 g_print("D-Bus thread leaving\n");
 return NULL;
}

int main(
 int argc,
 char *argv[])
{
 GError *error = NULL;
 GtkWidget *dialog = NULL;

 g_thread_init(NULL);
 gdk_threads_init();
 gdk_threads_enter();

 gtk_init(&argc, &argv);

 if (!g_thread_create
  (wait_for_dbus_messages, NULL, FALSE,
   &error)) {
  g_printerr
   ("Failed to create thread 1:%s\n",
   error->message);
  return 1;
 }
#ifdef SHOW_BROKEN_EXAMPLE
// this variety acts weird:
 dialog =
  gtk_file_chooser_dialog_new
  ("This example doesn't work right",
  NULL, GTK_FILE_CHOOSER_ACTION_OPEN,
  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
  GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
  NULL);

 if (gtk_dialog_run(GTK_DIALOG(dialog))
  == GTK_RESPONSE_ACCEPT) {
  char *filename =
   gtk_file_chooser_get_filename
   (GTK_FILE_CHOOSER(dialog));

  g_free(filename);
 }
#else
// this variety doesn't act weird:
 dialog = gtk_message_dialog_new(NULL,
  GTK_DIALOG_MODAL,
  GTK_MESSAGE_INFO,
  GTK_BUTTONS_OK,
  "This example works right");
 gtk_dialog_run(GTK_DIALOG(dialog));
#endif

 if (NULL != dialog)
  gtk_widget_destroy(dialog);

 gtk_main();
 gdk_threads_leave();

 return 0;
}



More information about the dbus mailing list