From d5695b1183ad4d895dae24a6048b8788f9e8d7d0 Mon Sep 17 00:00:00 2001
From: Giovanni Campagna <gcampagna@src.gnome.org>
Date: Sat, 8 Mar 2014 19:34:18 +0100
Subject: [PATCH 2/2] GWeatherInfo: don't abort the entire SoupSession

The SoupSession is shared between all GWeatherInfos, so it's
extremely bad to abort it, expecially because we do when infos
are finalized. Instead, have each info keep a list of pending
SoupMessages and cancel them.
---
 libgweather/weather-iwin.c  | 11 ++++++-----
 libgweather/weather-metar.c | 12 ++++++------
 libgweather/weather-owm.c   | 12 ++++++------
 libgweather/weather-priv.h  |  7 +++++--
 libgweather/weather-wx.c    | 13 +++++++------
 libgweather/weather-yahoo.c | 12 ++++++------
 libgweather/weather-yrno.c  | 24 ++++++++++++------------
 libgweather/weather.c       | 37 +++++++++++++++++++++++++++++++------
 8 files changed, 79 insertions(+), 49 deletions(-)

diff --git a/libgweather/weather-iwin.c b/libgweather/weather-iwin.c
index 5961878..1bc60f5 100644
--- a/libgweather/weather-iwin.c
+++ b/libgweather/weather-iwin.c
@@ -322,16 +322,17 @@ iwin_finish (SoupSession *session, SoupMessage *msg, gpointer data)
 
     if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
         /* forecast data is not really interesting anyway ;) */
-        g_warning ("Failed to get IWIN forecast data: %d %s\n",
-                   msg->status_code, msg->reason_phrase);
-        _gweather_info_request_done (info);
+	if (msg->status_code != SOUP_STATUS_CANCELLED)
+	    g_warning ("Failed to get IWIN forecast data: %d %s\n",
+		       msg->status_code, msg->reason_phrase);
+        _gweather_info_request_done (info, msg);
         return;
     }
 
     priv = info->priv;
     priv->forecast_list = parseForecastXml (msg->response_body->data, info);
 
-    _gweather_info_request_done (info);
+    _gweather_info_request_done (info, msg);
 }
 
 /* Get forecast into newly alloc'ed string */
@@ -370,9 +371,9 @@ iwin_start_open (GWeatherInfo *info)
     url = g_strdup_printf ("http://www.weather.gov/forecasts/xml/sample_products/browser_interface/ndfdBrowserClientByDay.php?&lat=%s&lon=%s&format=24+hourly&startDate=%04d-%02d-%02d&numDays=7",
 			   latstr, lonstr, 1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday);
     msg = soup_message_new ("GET", url);
+    _gweather_info_begin_request (info, msg);
     soup_session_queue_message (priv->session, msg, iwin_finish, info);
 
-    priv->requests_pending++;
     g_free (url);
 
     return TRUE;
diff --git a/libgweather/weather-metar.c b/libgweather/weather-metar.c
index 94ff2cc..d808e43 100644
--- a/libgweather/weather-metar.c
+++ b/libgweather/weather-metar.c
@@ -570,11 +570,12 @@ metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
 	    priv->network_error = TRUE;
 	else {
 	    /* Translators: %d is an error code, and %s the error string */
-	    g_warning (_("Failed to get METAR data: %d %s.\n"),
-		       msg->status_code, msg->reason_phrase);
+	    if (msg->status_code != SOUP_STATUS_CANCELLED)
+		g_warning (_("Failed to get METAR data: %d %s.\n"),
+			   msg->status_code, msg->reason_phrase);
 	}
 
-	_gweather_info_request_done (info);
+	_gweather_info_request_done (info, msg);
 	return;
     }
 
@@ -601,7 +602,7 @@ metar_finish (SoupSession *session, SoupMessage *msg, gpointer data)
     }
 
     priv->valid = success;
-    _gweather_info_request_done (info);
+    _gweather_info_request_done (info, msg);
 }
 
 /* Read current conditions and fill in info structure */
@@ -623,7 +624,6 @@ metar_start_open (GWeatherInfo *info)
 	"GET", "http://weather.noaa.gov/cgi-bin/mgetmetar.pl",
 	"cccc", loc->code,
 	NULL);
+    _gweather_info_begin_request (info, msg);
     soup_session_queue_message (priv->session, msg, metar_finish, info);
-
-    priv->requests_pending++;
 }
diff --git a/libgweather/weather-owm.c b/libgweather/weather-owm.c
index 40a8832..b23cd56 100644
--- a/libgweather/weather-owm.c
+++ b/libgweather/weather-owm.c
@@ -400,14 +400,15 @@ owm_finish (SoupSession *session,
 
     if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
 	/* forecast data is not really interesting anyway ;) */
-	g_message ("Failed to get OpenWeatherMap forecast data: %d %s\n",
-		   msg->status_code, msg->reason_phrase);
-	_gweather_info_request_done (info);
+	if (msg->status_code != SOUP_STATUS_CANCELLED)
+	    g_message ("Failed to get OpenWeatherMap forecast data: %d %s\n",
+		       msg->status_code, msg->reason_phrase);
+	_gweather_info_request_done (info, msg);
 	return;
     }
 
     parse_forecast_xml (info, msg->response_body);
-    _gweather_info_request_done (info);
+    _gweather_info_request_done (info, msg);
 }
 
 gboolean
@@ -440,10 +441,9 @@ owm_start_open (GWeatherInfo *info)
     url = g_strdup_printf (template, latstr, lonstr);
 
     message = soup_message_new ("GET", url);
+    _gweather_info_begin_request (info, message);
     soup_session_queue_message (priv->session, message, owm_finish, info);
 
-    priv->requests_pending++;
-
     g_free (url);
 
     return TRUE;
diff --git a/libgweather/weather-priv.h b/libgweather/weather-priv.h
index c9e4b73..8bea95b 100644
--- a/libgweather/weather-priv.h
+++ b/libgweather/weather-priv.h
@@ -133,7 +133,7 @@ struct _GWeatherInfoPrivate {
     GdkPixbufLoader *radar_loader;
     GdkPixbufAnimation *radar;
     SoupSession *session;
-    gint requests_pending;
+    GSList *requests_pending;
 };
 
 /* Values common to the parsing source files */
@@ -190,7 +190,10 @@ gboolean        owm_start_open          (GWeatherInfo *info);
 gboolean	metar_parse		(gchar *metar,
 					 GWeatherInfo *info);
 
-void		_gweather_info_request_done (GWeatherInfo *info);
+void            _gweather_info_begin_request (GWeatherInfo *info,
+					      SoupMessage  *message);
+void		_gweather_info_request_done (GWeatherInfo *info,
+					     SoupMessage  *message);
 
 void		ecl2equ			(gdouble t,
 					 gdouble eclipLon,
diff --git a/libgweather/weather-wx.c b/libgweather/weather-wx.c
index 567e072..2701dce 100644
--- a/libgweather/weather-wx.c
+++ b/libgweather/weather-wx.c
@@ -34,10 +34,11 @@ wx_finish (SoupSession *session, SoupMessage *msg, gpointer data)
     priv = info->priv;
 
     if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
-	g_warning ("Failed to get radar map image: %d %s.\n",
-		   msg->status_code, msg->reason_phrase);
+	if (msg->status_code != SOUP_STATUS_CANCELLED)
+	    g_warning ("Failed to get radar map image: %d %s.\n",
+		       msg->status_code, msg->reason_phrase);
 	g_object_unref (priv->radar_loader);
-	_gweather_info_request_done (info);
+	_gweather_info_request_done (info, msg);
 	return;
     }
 
@@ -51,7 +52,7 @@ wx_finish (SoupSession *session, SoupMessage *msg, gpointer data)
     }
     g_object_unref (priv->radar_loader);
 
-    _gweather_info_request_done (info);
+    _gweather_info_request_done (info, msg);
 }
 
 static void
@@ -103,8 +104,8 @@ wx_start_open (GWeatherInfo *info)
 
     g_signal_connect (msg, "got-chunk", G_CALLBACK (wx_got_chunk), info);
     soup_message_body_set_accumulate (msg->response_body, FALSE);
+    _gweather_info_begin_request (info, msg);
     soup_session_queue_message (priv->session, msg, wx_finish, info);
-    g_free (url);
 
-    priv->requests_pending++;
+    g_free (url);
 }
diff --git a/libgweather/weather-yahoo.c b/libgweather/weather-yahoo.c
index 778169e..a44ae21 100644
--- a/libgweather/weather-yahoo.c
+++ b/libgweather/weather-yahoo.c
@@ -249,14 +249,15 @@ yahoo_finish (SoupSession *session,
 
     if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
 	/* forecast data is not really interesting anyway ;) */
-	g_warning ("Failed to get Yahoo! Weather forecast data: %d %s\n",
-		   msg->status_code, msg->reason_phrase);
-	_gweather_info_request_done (info);
+	if (msg->status_code != SOUP_STATUS_CANCELLED)
+	    g_warning ("Failed to get Yahoo! Weather forecast data: %d %s\n",
+		       msg->status_code, msg->reason_phrase);
+	_gweather_info_request_done (info, msg);
 	return;
     }
 
     parse_forecast_xml (info, msg->response_body);
-    _gweather_info_request_done (info);
+    _gweather_info_request_done (info, msg);
 }
 
 gboolean
@@ -280,10 +281,9 @@ yahoo_start_open (GWeatherInfo *info)
     url = g_strdup_printf("http://weather.yahooapis.com/forecastrss?w=%s&u=f", loc->yahoo_id);
 
     message = soup_message_new ("GET", url);
+    _gweather_info_begin_request (info, message);
     soup_session_queue_message (priv->session, message, yahoo_finish, info);
 
-    priv->requests_pending++;
-
     g_free (url);
 
     return TRUE;
diff --git a/libgweather/weather-yrno.c b/libgweather/weather-yrno.c
index 6f07e16..05d43a9 100644
--- a/libgweather/weather-yrno.c
+++ b/libgweather/weather-yrno.c
@@ -463,14 +463,15 @@ yrno_finish_old (SoupSession *session,
 
     if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
 	/* forecast data is not really interesting anyway ;) */
-	g_message ("Failed to get Yr.no forecast data: %d %s\n",
-		   msg->status_code, msg->reason_phrase);
-	_gweather_info_request_done (info);
+	if (msg->status_code != SOUP_STATUS_CANCELLED)
+	    g_message ("Failed to get Yr.no forecast data: %d %s\n",
+		       msg->status_code, msg->reason_phrase);
+	_gweather_info_request_done (info, msg);
 	return;
     }
 
     parse_forecast_xml_old (info, msg->response_body);
-    _gweather_info_request_done (info);
+    _gweather_info_request_done (info, msg);
 }
 
 static gboolean
@@ -487,10 +488,9 @@ yrno_start_open_old (GWeatherInfo *info)
 	return FALSE;
 
     message = soup_message_new ("GET", url);
+    _gweather_info_begin_request (info, message);
     soup_session_queue_message (priv->session, message, yrno_finish_old, info);
 
-    priv->requests_pending++;
-
     g_free (url);
 
     return TRUE;
@@ -505,15 +505,16 @@ yrno_finish_new (SoupSession *session,
 
     if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
 	/* forecast data is not really interesting anyway ;) */
-	g_message ("Failed to get Yr.no forecast data: %d %s\n",
-		   msg->status_code, msg->reason_phrase);
-	_gweather_info_request_done (info);
+	if (msg->status_code != SOUP_STATUS_CANCELLED)
+	    g_message ("Failed to get Yr.no forecast data: %d %s\n",
+		       msg->status_code, msg->reason_phrase);
+	_gweather_info_request_done (info, msg);
 	return;
     }
 
     parse_forecast_xml_new (info, msg->response_body);
 
-    _gweather_info_request_done (info);
+    _gweather_info_request_done (info, msg);
 }
 
 static gboolean
@@ -539,10 +540,9 @@ yrno_start_open_new (GWeatherInfo *info)
     url = g_strdup_printf("http://api.yr.no/weatherapi/locationforecast/1.8/?lat=%s;lon=%s", latstr, lonstr);
 
     message = soup_message_new ("GET", url);
+    _gweather_info_begin_request (info, message);
     soup_session_queue_message (priv->session, message, yrno_finish_new, info);
 
-    priv->requests_pending++;
-
     g_free (url);
 
     return TRUE;
diff --git a/libgweather/weather.c b/libgweather/weather.c
index b0d40d1..4cca36b 100644
--- a/libgweather/weather.c
+++ b/libgweather/weather.c
@@ -226,9 +226,21 @@ requests_init (GWeatherInfo *info)
 }
 
 void
-_gweather_info_request_done (GWeatherInfo *info)
+_gweather_info_begin_request (GWeatherInfo *info,
+			      SoupMessage  *message)
 {
-    if (!--info->priv->requests_pending)
+    info->priv->requests_pending = g_slist_prepend (info->priv->requests_pending, message);
+    g_object_ref (message);
+}
+
+void
+_gweather_info_request_done (GWeatherInfo *info,
+			     SoupMessage  *message)
+{
+    info->priv->requests_pending = g_slist_remove (info->priv->requests_pending, message);
+    g_object_ref (message);
+
+    if (info->priv->requests_pending == NULL)
         g_signal_emit (info, gweather_info_signals[SIGNAL_UPDATED], 0);
 }
 
@@ -423,7 +435,7 @@ settings_changed_cb (GSettings    *settings,
        Otherwise just wait for the update that will happen at
        the end
     */
-    if (priv->requests_pending == 0)
+    if (priv->requests_pending == NULL)
         g_signal_emit (info, gweather_info_signals[SIGNAL_UPDATED], 0);
 }
 
@@ -589,12 +601,25 @@ gweather_info_update (GWeatherInfo *info)
 void
 gweather_info_abort (GWeatherInfo *info)
 {
+    GSList *list, *iter;
+    GSList dummy = { NULL, NULL };
+
     g_return_if_fail (GWEATHER_IS_INFO (info));
 
-    if (info->priv->session) {
-	soup_session_abort (info->priv->session);
-	info->priv->requests_pending = 0;
+    if (info->priv->session == NULL) {
+	g_assert (info->priv->requests_pending == NULL);
+	return;
     }
+
+    list = info->priv->requests_pending;
+    /* to block updated signals */
+    info->priv->requests_pending = &dummy;
+
+    for (iter = list; iter; iter = iter->next)
+	soup_session_cancel_message (info->priv->session, iter->data, SOUP_STATUS_CANCELLED);
+    g_slist_free (list);
+
+    info->priv->requests_pending = NULL;
 }
 
 static void
-- 
1.8.4

