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