GNOME Bugzilla – Bug 494173
soup_session_send_message locks up after leaving gtk_main
Last modified: 2007-11-21 16:46:18 UTC
When calling soup_session_send_message on a async session outside of a gtk_main loop the program looks up. Guess libsoup should detect that situation and work arround somehow.
+ Trace 175737
/* Minimum test case. * When commenting out gtk_dialog_run no dead-lock occurs. */ #include <libsoup/soup-session-async.h> #include <gtk/gtk.h> int main (int argc, char *argv[]) { GtkWidget *dialog; SoupSession *session; SoupMessage *message; guint status; g_thread_init (NULL); gdk_threads_init (); gtk_init (&argc, &argv); dialog = gtk_message_dialog_new (NULL, 0, GTK_MESSAGE_INFO, GTK_BUTTONS_CLOSE, "Yadda, dadda"); gtk_dialog_run (GTK_DIALOG (dialog)); message = soup_message_new ("GET", "http://gnome.org/"); session = soup_session_async_new (); g_debug ("%s: sending request...", G_STRLOC); status = soup_session_send_message (session, message); g_debug ("%s: status: %d", G_STRLOC, status); g_object_unref (session); g_object_unref (message); return 0; }
Calling gdk_threads_set_lock_functions to replace GDK's locking functions with lock-counting functions reveals the test case enters a recursive-lock situation. So it seems either soup_session_send_message has to be surrounded by gdk_threads_leave/enter calls, or the GDK lock finally has to become recursive.
I'm not especially clued-in about gtk and threads, but it seems to me that this can't be libsoup's fault, given that libsoup knows nothing about gdk and its locking conventions (and in particular, libsoup can't call gdk_threads_enter(), since it doesn't depend on libgdk). AFAICT, the problem is that the default GMainContext is in a non-working state after gtk_main() exits, which would be a gtk bug. Right?
The gdk threads docs (http://library.gnome.org/devel/gdk/stable/gdk-Threads.html) suggest that you are supposed to surround the call to gtk_main() with gdk_threads_enter() and gdk_threads_leave(), and they say explicitly "you must also surround any calls to GTK+ not made within a signal handler with a gdk_threads_enter()/gdk_threads_leave() pair." Putting "gdk_threads_enter()" before the gtk_message_dialog_new(), and "gdk_threads_leave()" after the gtk_dialog_run() fixes the hang. (In fact, only the "leave" is actually necessary.) Depending on exactly what you're doing, a better solution might be to give the SoupSession its own GMainContext (via the SOUP_SESSION_ASYNC_CONTEXT property), so it runs independently of the default main loop. However, this currently requires libsoup from svn to work right. (The fix will go out in 2.2.104 next week.)