Index: ChangeLog
===================================================================
--- ChangeLog	(revision 1159)
+++ ChangeLog	(working copy)
@@ -1,3 +1,16 @@
+2008-09-17  Dan Winship  <danw@gnome.org>
+
+	* libsoup/soup-session.c (connect_result): ref the session around
+	the "cancel all messages waiting for this connection" loop, since
+	the message callback might unref the session
+
+	* libsoup/soup-session-async.c (run_queue): ref the session before
+	calling soup_connection_connect_async().
+	(got_connection): And drop that ref here, bailing out without
+	doing anything else if that was the last ref. (This is messy, but
+	so is everything else with SoupConnection. Will be fixed when the
+	proxy/connection rewrite is merged.)
+
 2008-09-08  Dan Winship  <danw@gnome.org>
 
 	* configure.in: 2.23.92
Index: libsoup/soup-session-async.c
===================================================================
--- libsoup/soup-session-async.c	(revision 1158)
+++ libsoup/soup-session-async.c	(working copy)
@@ -85,6 +85,18 @@ soup_session_async_new_with_options (con
 }
 
 
+static gboolean
+still_exists_after_unref (gpointer obj)
+{
+	g_object_add_weak_pointer (obj, (gpointer)&obj);
+	g_object_unref (obj);
+	if (obj) {
+		g_object_remove_weak_pointer (obj, (gpointer)&obj);
+		return TRUE;
+	}
+	return FALSE;
+}
+
 static void
 connection_closed (SoupConnection *conn, gpointer session)
 {
@@ -99,6 +111,16 @@ got_connection (SoupConnection *conn, gu
 {
 	SoupSessionAsync *sa = user_data;
 
+	/* If the new connection failed,
+	 * soup-session.c:connect_result() might have cancelled the
+	 * messages that were waiting for it, which might have caused
+	 * the app to unref the session. So it's possible that when we
+	 * drop the ref added by run_queue() that the session will be
+	 * destroyed.
+	 */
+	if (!still_exists_after_unref (sa))
+		return;
+
 	if (status != SOUP_STATUS_OK) {
 		/* The connection attempt failed, and thus @conn was
 		 * closed and the open connection count for the
@@ -158,7 +180,7 @@ run_queue (SoupSessionAsync *sa)
 
 		if (is_new) {
 			soup_connection_connect_async (conn, got_connection,
-						       session);
+						       g_object_ref (session));
 		} else
 			soup_connection_send_request (conn, msg);
 	}
@@ -195,24 +217,20 @@ final_finished (SoupMessage *req, gpoint
 	SoupSessionAsyncQueueData *saqd = user_data;
 	SoupSessionAsync *sa = saqd->sa;
 
-	g_object_add_weak_pointer (G_OBJECT (sa), (gpointer)&sa);
-
+	g_object_ref (sa);
 	if (!SOUP_MESSAGE_IS_STARTING (req)) {
 		g_signal_handlers_disconnect_by_func (req, final_finished, saqd);
 		if (saqd->callback) {
 			saqd->callback ((SoupSession *)sa, req,
 					saqd->callback_data);
-			/* callback might destroy sa */
 		}
 
 		g_object_unref (req);
 		g_slice_free (SoupSessionAsyncQueueData, saqd);
 	}
 
-	if (sa) {
-		g_object_remove_weak_pointer (G_OBJECT (sa), (gpointer)&sa);
+	if (still_exists_after_unref (sa))
 		run_queue (sa);
-	}
 }
 
 static gboolean
@@ -220,13 +238,8 @@ idle_run_queue (gpointer user_data)
 {
 	SoupSessionAsync *sa = user_data;
 
-	g_object_add_weak_pointer (G_OBJECT (sa), (gpointer)&sa);
-	g_object_unref (sa);
-
-	if (sa) {
-		g_object_remove_weak_pointer (G_OBJECT (sa), (gpointer)&sa);
+	if (still_exists_after_unref (sa))
 		run_queue (sa);
-	}
 	return FALSE;
 }
 
Index: libsoup/soup-session.c
===================================================================
--- libsoup/soup-session.c	(revision 1158)
+++ libsoup/soup-session.c	(working copy)
@@ -962,6 +962,7 @@ connect_result (SoupConnection *conn, gu
 	 * any messages waiting for this host, since they're out
 	 * of luck.
 	 */
+	g_object_ref (session);
 	for (msg = soup_message_queue_first (priv->queue, &iter); msg; msg = soup_message_queue_next (priv->queue, &iter)) {
 		if (get_host_for_message (session, msg) == host) {
 			if (status == SOUP_STATUS_TRY_AGAIN) {
@@ -973,6 +974,7 @@ connect_result (SoupConnection *conn, gu
 			}
 		}
 	}
+	g_object_unref (session);
 }
 
 /**
