Re: Strange interaction between GtkDialog and a GThread
- From: Gnaural <gnaural users sourceforge net>
- To: "gtk-app-devel-list gnome.org" <gtk-app-devel-list gnome org>
- Subject: Re: Strange interaction between GtkDialog and a GThread
- Date: Tue, 27 Nov 2007 14:15:45 -0800 (PST)
Thanks for the reply. Interesting. Replacing sleep()
with select() did return an error with errno == EINTR.
If I understand you correctly, this is a clue that
gtk_file_chooser_dialog_new is calling alarm()
somewhere.
That may indeed factor in to what I am trying to
solve. But fact is, getting a thread to sleep wasn't
really my goal, I just used that to make a simple
example that would "break."
The real challenge I've been having for a couple weeks
is with a thread running a blocking D-Bus server. The
server works great, but if I launch a
gtk_file_chooser_dialog_new, the entire app goes very
weird! Below is as simple an example as I could make
(without the client; I could paste that code too if
wanted, but it is not needed to see the weirdness).
Basically, the inconsistent results look like some
kind of deadlock; usually on my system, it will not
open the dialog, but if the dialog does open, it is
dead. Yet normally the D-Bus thread happily continues
to serve clients. But not always. Strangest to me is
the backtrace; before the call to
gtk_file_chooser_dialog_new, the main thread has (as
one would expect) no calls to libdbus-1.so.3; after
the call to gtk_file_chooser_dialog_new, the main
thread is polluted with myriad calls to
libdbus-1.so.3., as if it merged with the other
thread. Initially, I thought this was a D-Bus problem,
so I posted to the D-Bus list; then I started to think
it was a GTK issue, so I've posted here. BTW, the
D-Bus list did offer one interesting response about
how what I see may be related to the strange code
behind gtk_dialog_run, in that it "re-enters the main
loop." I did look at it's code, and it did mystify me.
Here's the thread:
[
http://lists.freedesktop.org/archives/dbus/2007-November/008968.html
]
Any ideas?
Thanks again!
//////////////////////////////////////
/*
Demonstration of strange
gtk_file_chooser_dialog_new/dbus
interaction.
Compile with:
gcc main.c -o HelloThreadBreaker \
`pkg-config --cflags --libs \
gtk+-2.0 gthread-2.0 dbus-1`
*/
#include <unistd.h>
#include <gtk/gtk.h>
#include <dbus/dbus.h>
#define GNAURAL_DBUS_SERVER "org.gnaural.Server"
#define GNAURAL_DBUS_INTERFACE "org.gnaural.Interface"
DBusConnection *main_remote_connection = NULL;
time_t main_startime;
/////////////////////////////
void GetBeatfreq (DBusMessage * msg, DBusConnection *
conn)
{
DBusMessage *reply;
DBusMessageIter args;
unsigned int voice = 0;
if (!dbus_message_iter_init (msg, &args))
{
fprintf (stderr, "Message has no arguments\n");
}
else if (DBUS_TYPE_UINT32 !=
dbus_message_iter_get_arg_type (&args))
{
fprintf (stderr, "Argument is not
DBUS_TYPE_UINT32\n");
}
else
{
dbus_message_iter_get_basic (&args, &voice);
}
reply = dbus_message_new_method_return (msg);
double result = (double) (time (NULL) -
main_startime);
dbus_message_iter_init_append (reply, &args);
if (!dbus_message_iter_append_basic (&args,
DBUS_TYPE_DOUBLE, &result))
{
fprintf (stderr, "Out Of Memory\n");
return;
}
if (!dbus_connection_send (conn, reply, NULL))
{
fprintf (stderr, "Out Of Memory\n");
return;
}
dbus_connection_flush (conn);
dbus_message_unref (reply);
}
/////////////////////////////
int main_init_connection (void)
{
DBusError err;
int ret;
dbus_error_init (&err);
main_remote_connection = 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);
}
if (NULL == main_remote_connection)
{
fprintf (stderr, "Connection Null\n");
return 1;
}
ret =
dbus_bus_request_name (main_remote_connection,
GNAURAL_DBUS_SERVER,
DBUS_NAME_FLAG_REPLACE_EXISTING, &err);
if (dbus_error_is_set (&err))
{
fprintf (stderr, "Name Error (%s)\n", err.message);
dbus_error_free (&err);
}
if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret)
{
fprintf (stderr, "Not Primary Owner (%d)\n", ret);
return 1;
}
return 0;
}
////////////////////////////////
void main_check_for_methodcall (gpointer arg)
{
DBusMessage *msg;
if (NULL == main_remote_connection)
{
fprintf (stderr, "Connection invalid!\n");
return;
}
fprintf (stderr, "Entering blocking loop\n");
while (dbus_connection_read_write_dispatch
(main_remote_connection, -1))
{
msg = dbus_connection_pop_message
(main_remote_connection);
if (NULL == msg)
{
fprintf (stderr, "Message == NULL\n");
continue;
}
else
{
fprintf (stderr, "Got Something... ");
}
if (dbus_message_is_method_call (msg, //DBusMessage *
msg
GNAURAL_DBUS_INTERFACE,//char * interface
"GetBeatfreq"))//char * method
{
GetBeatfreq (msg, main_remote_connection);
fprintf (stderr, "Running GetBeatfreq\n");
}
else
{
fprintf (stderr, "Call not recognized\n");
}
dbus_message_unref (msg);
}
fprintf (stderr, "Leaving wait for methodcall
loop\n");
}
//////////////////////////////////
void *sleep_for_awhile (void *args)
{
time_t t1;
time_t t2;
g_print ("Sleeping for 2 seconds\n");
time (&t1);
sleep (1);
time (&t2);
g_print ("Slept for %d seconds\n", (int) (t2 - t1));
main_init_connection ();
g_print ("Blocking forever\n");
main_check_for_methodcall (NULL);
time (&t2);
g_print ("Blocked for %d seconds\n", (int) (t2 - t1));
g_print ("Thread terminated naturally\n");
return NULL;
}
////////////////////////////////
int main (int argc, char *argv[])
{
GError *error = NULL;
GtkWidget *dialog = NULL;
time (&main_startime);
g_thread_init (NULL);
gdk_threads_init ();
gdk_threads_enter ();
gtk_init (&argc, &argv);
if (!g_thread_create (sleep_for_awhile, NULL, FALSE,
&error))
{
g_printerr ("g_thread_create failed:%s\n",
error->message);
return 1;
}
//this does not work with thread:
dialog = gtk_file_chooser_dialog_new ("Open File",
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)
{
g_free (gtk_file_chooser_get_filename
(GTK_FILE_CHOOSER (dialog)));
}
/*
//this variety does work with thread:
dialog = gtk_message_dialog_new (NULL,
GTK_DIALOG_MODAL,
GTK_MESSAGE_INFO, GTK_BUTTONS_OK,
"Message Box");
gtk_dialog_run (GTK_DIALOG (dialog));
*/
gtk_widget_destroy (dialog);
gtk_main ();
gdk_threads_leave ();
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]