[libsoup] SoupSessionAsync: fix the idle_run_queue source handling (again)



commit 9281a4f2088428557b9f1a458eb9446ddc2a97f2
Author: Dan Winship <danw gnome org>
Date:   Sun Aug 12 10:32:49 2012 -0400

    SoupSessionAsync: fix the idle_run_queue source handling (again)
    
    The previous code checked priv->disposed after the session was freed
    sometimes...

 libsoup/soup-misc-private.h  |    4 ++++
 libsoup/soup-misc.c          |   21 +++++++++++++++++----
 libsoup/soup-session-async.c |   18 ++++++++++++++++--
 3 files changed, 37 insertions(+), 6 deletions(-)
---
diff --git a/libsoup/soup-misc-private.h b/libsoup/soup-misc-private.h
index 0677fc5..79e73bc 100644
--- a/libsoup/soup-misc-private.h
+++ b/libsoup/soup-misc-private.h
@@ -41,4 +41,8 @@ SoupURI *soup_socket_get_http_proxy_uri (SoupSocket *sock);
 					   method == SOUP_METHOD_PUT || \
 					   method == SOUP_METHOD_DELETE)
 
+GSource *soup_add_completion_reffed (GMainContext *async_context,
+				     GSourceFunc   function,
+				     gpointer      data);
+
 #endif /* SOUP_MISC_PRIVATE_H */
diff --git a/libsoup/soup-misc.c b/libsoup/soup-misc.c
index 8354045..325b587 100644
--- a/libsoup/soup-misc.c
+++ b/libsoup/soup-misc.c
@@ -8,6 +8,7 @@
 #include <string.h>
 
 #include "soup-misc.h"
+#include "soup-misc-private.h"
 
 /**
  * SECTION:soup-misc
@@ -112,6 +113,19 @@ soup_add_idle (GMainContext *async_context,
 	return source;
 }
 
+GSource *
+soup_add_completion_reffed (GMainContext *async_context,
+			    GSourceFunc   function,
+			    gpointer      data)
+{
+	GSource *source = g_idle_source_new ();
+
+	g_source_set_priority (source, G_PRIORITY_DEFAULT);
+	g_source_set_callback (source, function, data, NULL);
+	g_source_attach (source, async_context);
+	return source;
+}
+
 /**
  * soup_add_completion: (skip)
  * @async_context: (allow-none): the #GMainContext to dispatch the I/O
@@ -132,10 +146,9 @@ GSource *
 soup_add_completion (GMainContext *async_context,
 	             GSourceFunc function, gpointer data)
 {
-	GSource *source = g_idle_source_new ();
-	g_source_set_priority (source, G_PRIORITY_DEFAULT);
-	g_source_set_callback (source, function, data, NULL);
-	g_source_attach (source, async_context);
+	GSource *source;
+
+	source = soup_add_completion_reffed (async_context, function, data);
 	g_source_unref (source);
 	return source;
 }
diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c
index 75929ed..0f365f3 100644
--- a/libsoup/soup-session-async.c
+++ b/libsoup/soup-session-async.c
@@ -16,6 +16,7 @@
 #include "soup-session-private.h"
 #include "soup-message-private.h"
 #include "soup-message-queue.h"
+#include "soup-misc-private.h"
 
 /**
  * SECTION:soup-session-async
@@ -37,6 +38,7 @@ G_DEFINE_TYPE (SoupSessionAsync, soup_session_async, SOUP_TYPE_SESSION)
 
 typedef struct {
 	SoupSessionAsync *sa;
+	GSList *sources;
 	gboolean disposed;
 
 } SoupSessionAsyncPrivate;
@@ -54,8 +56,14 @@ static void
 soup_session_async_dispose (GObject *object)
 {
 	SoupSessionAsyncPrivate *priv = SOUP_SESSION_ASYNC_GET_PRIVATE (object);
+	GSList *iter;
 
 	priv->disposed = TRUE;
+	for (iter = priv->sources; iter; iter = iter->next) {
+		g_source_destroy (iter->data);
+		g_source_unref (iter->data);
+	}
+	g_clear_pointer (&priv->sources, g_slist_free);
 
 	G_OBJECT_CLASS (soup_session_async_parent_class)->dispose (object);
 }
@@ -359,12 +367,17 @@ static gboolean
 idle_run_queue (gpointer user_data)
 {
 	SoupSessionAsyncPrivate *priv = user_data;
+	GSource *source;
 
 	if (priv->disposed)
 		return FALSE;
 
+	source = g_main_current_source ();
+	priv->sources = g_slist_remove (priv->sources, source);
+
 	/* Ensure that the source is destroyed before running the queue */
-	g_source_destroy (g_main_current_source ());
+	g_source_destroy (source);
+	g_source_unref (source);
 
 	run_queue (priv->sa);
 	return FALSE;
@@ -389,7 +402,8 @@ do_idle_run_queue (SoupSession *session)
 	if (source)
 		return;
 
-	source = soup_add_completion (async_context, idle_run_queue, priv);
+	source = soup_add_completion_reffed (async_context, idle_run_queue, priv);
+	priv->sources = g_slist_prepend (priv->sources, source);
 }
 
 static void



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]