[libsoup] soup-cache: fix several leaks.
- From: Sergio Villar Senin <svillar src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libsoup] soup-cache: fix several leaks.
- Date: Mon, 13 Jun 2011 14:39:20 +0000 (UTC)
commit 15c9ad908b4758b4e976bd27d14ce82847133e5e
Author: Sergio Villar Senin <svillar igalia com>
Date: Mon Jun 13 14:13:06 2011 +0200
soup-cache: fix several leaks.
We were incorrectly using the GVariant API to serialize/deserialize cache
contents. The consequence is that several leaks were created when loading
and dumping the cache.
https://bugzilla.gnome.org/show_bug.cgi?id=649309
libsoup/soup-cache.c | 106 ++++++++++++++++++++++++++++----------------------
1 files changed, 59 insertions(+), 47 deletions(-)
---
diff --git a/libsoup/soup-cache.c b/libsoup/soup-cache.c
index 5816e58..73064d9 100644
--- a/libsoup/soup-cache.c
+++ b/libsoup/soup-cache.c
@@ -30,6 +30,7 @@
#endif
#include <stdlib.h>
+#include <string.h>
#include <gio/gio.h>
#define LIBSOUP_USE_UNSTABLE_REQUEST_API
@@ -1554,29 +1555,32 @@ pack_entry (gpointer data,
SoupCacheEntry *entry = (SoupCacheEntry *) data;
SoupMessageHeadersIter iter;
const gchar *header_key, *header_value;
- GVariantBuilder *headers_builder;
GVariantBuilder *entries_builder = (GVariantBuilder *)user_data;
/* Do not store non-consolidated entries */
if (entry->dirty || entry->writing || !entry->key)
return;
+ g_variant_builder_open (entries_builder, G_VARIANT_TYPE (SOUP_CACHE_PHEADERS_FORMAT));
+ g_variant_builder_add (entries_builder, "s", entry->key);
+ g_variant_builder_add (entries_builder, "s", entry->filename);
+ g_variant_builder_add (entries_builder, "b", entry->must_revalidate);
+ g_variant_builder_add (entries_builder, "u", entry->freshness_lifetime);
+ g_variant_builder_add (entries_builder, "u", entry->corrected_initial_age);
+ g_variant_builder_add (entries_builder, "u", entry->response_time);
+ g_variant_builder_add (entries_builder, "u", entry->hits);
+ g_variant_builder_add (entries_builder, "u", entry->length);
+
/* Pack headers */
- headers_builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
+ g_variant_builder_open (entries_builder, G_VARIANT_TYPE ("a" SOUP_CACHE_HEADERS_FORMAT));
soup_message_headers_iter_init (&iter, entry->headers);
while (soup_message_headers_iter_next (&iter, &header_key, &header_value)) {
if (g_utf8_validate (header_value, -1, NULL))
- g_variant_builder_add (headers_builder, SOUP_CACHE_HEADERS_FORMAT,
+ g_variant_builder_add (entries_builder, SOUP_CACHE_HEADERS_FORMAT,
header_key, header_value);
}
-
- /* Entry data */
- g_variant_builder_add (entries_builder, SOUP_CACHE_PHEADERS_FORMAT,
- entry->key, entry->filename, entry->must_revalidate,
- entry->freshness_lifetime, entry->corrected_initial_age,
- entry->response_time, entry->hits, entry->length, headers_builder);
-
- g_variant_builder_unref (headers_builder);
+ g_variant_builder_close (entries_builder); /* "a" SOUP_CACHE_HEADERS_FORMAT */
+ g_variant_builder_close (entries_builder); /* SOUP_CACHE_PHEADERS_FORMAT */
}
void
@@ -1584,20 +1588,19 @@ soup_cache_dump (SoupCache *cache)
{
SoupCachePrivate *priv = SOUP_CACHE_GET_PRIVATE (cache);
gchar *filename;
- GVariantBuilder *entries_builder;
+ GVariantBuilder entries_builder;
GVariant *cache_variant;
if (!g_list_length (cache->priv->lru_start))
return;
/* Create the builder and iterate over all entries */
- entries_builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
- g_list_foreach (cache->priv->lru_start, pack_entry, entries_builder);
+ g_variant_builder_init (&entries_builder, G_VARIANT_TYPE (SOUP_CACHE_ENTRIES_FORMAT));
+ g_list_foreach (cache->priv->lru_start, pack_entry, &entries_builder);
/* Serialize and dump */
- cache_variant = g_variant_new (SOUP_CACHE_ENTRIES_FORMAT, entries_builder);
- g_variant_builder_unref (entries_builder);
-
+ cache_variant = g_variant_builder_end (&entries_builder);
+ g_variant_ref_sink (cache_variant);
filename = g_build_filename (priv->cache_dir, SOUP_CACHE_FILE, NULL);
g_file_set_contents (filename, (const gchar *)g_variant_get_data (cache_variant),
g_variant_get_size (cache_variant), NULL);
@@ -1608,11 +1611,13 @@ soup_cache_dump (SoupCache *cache)
void
soup_cache_load (SoupCache *cache)
{
- gchar *filename = NULL, *contents = NULL;
+ gboolean must_revalidate;
+ uint freshness_lifetime, hits;
+ time_t corrected_initial_age, response_time;
+ char *key, *filename = NULL, *contents = NULL;
GVariant *cache_variant;
- GVariantIter *entries_iter, *headers_iter;
- GVariantType *variant_format;
- gsize length;
+ GVariantIter entries_iter, *headers_iter = NULL;
+ gsize length, items;
SoupCacheEntry *entry;
SoupCachePrivate *priv = cache->priv;
@@ -1624,45 +1629,52 @@ soup_cache_load (SoupCache *cache)
}
g_free (filename);
- variant_format = g_variant_type_new (SOUP_CACHE_ENTRIES_FORMAT);
- cache_variant = g_variant_new_from_data (variant_format, (const gchar *)contents, length, FALSE, g_free, contents);
- g_variant_type_free (variant_format);
-
- g_variant_get (cache_variant, SOUP_CACHE_ENTRIES_FORMAT, &entries_iter);
- entry = g_slice_new0 (SoupCacheEntry);
+ cache_variant = g_variant_new_from_data (G_VARIANT_TYPE (SOUP_CACHE_ENTRIES_FORMAT),
+ (const gchar *) contents, length, FALSE, g_free, contents);
+ items = g_variant_iter_init (&entries_iter, cache_variant);
+ g_debug ("Loading %"G_GSIZE_FORMAT" items from cache", items);
- while (g_variant_iter_loop (entries_iter, SOUP_CACHE_PHEADERS_FORMAT,
- &entry->key, &entry->filename, &entry->must_revalidate,
- &entry->freshness_lifetime, &entry->corrected_initial_age,
- &entry->response_time, &entry->hits, &entry->length,
+ while (g_variant_iter_loop (&entries_iter, SOUP_CACHE_PHEADERS_FORMAT,
+ &key, &filename, &must_revalidate,
+ &freshness_lifetime, &corrected_initial_age,
+ &response_time, &hits, &length,
&headers_iter)) {
const gchar *header_key, *header_value;
+ SoupMessageHeaders *headers;
+ SoupMessageHeadersIter soup_headers_iter;
/* SoupMessage Headers */
- entry->headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE);
- while (g_variant_iter_loop (headers_iter, SOUP_CACHE_DECODE_HEADERS_FORMAT, &header_key, &header_value))
- soup_message_headers_append (entry->headers, header_key, header_value);
+ headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE);
+ while (g_variant_iter_loop (headers_iter, SOUP_CACHE_HEADERS_FORMAT, &header_key, &header_value))
+ if (*header_key && *header_value)
+ soup_message_headers_append (headers, header_key, header_value);
+
+ /* Check that we have headers */
+ soup_message_headers_iter_init (&soup_headers_iter, headers);
+ if (!soup_message_headers_iter_next (&soup_headers_iter, &header_key, &header_value)) {
+ soup_message_headers_free (headers);
+ continue;
+ }
/* Insert in cache */
- if (!soup_cache_entry_insert_by_key (cache, (const gchar *)entry->key, entry, FALSE))
- soup_cache_entry_free (entry, TRUE);
-
- /* New entry for the next iteration. This creates an
- extra object the last iteration but it's worth it
- as we save several if's */
entry = g_slice_new0 (SoupCacheEntry);
+ entry->key = g_strdup (key);
+ entry->filename = g_strdup (filename);
+ entry->must_revalidate = must_revalidate;
+ entry->freshness_lifetime = freshness_lifetime;
+ entry->corrected_initial_age = corrected_initial_age;
+ entry->response_time = response_time;
+ entry->hits = hits;
+ entry->length = length;
+ entry->headers = headers;
+
+ if (!soup_cache_entry_insert_by_key (cache, entry->key, entry, FALSE))
+ soup_cache_entry_free (entry, TRUE);
}
- /* Remove last created entry */
- g_slice_free (SoupCacheEntry, entry);
- /* Sort LRU (shouldn't be needed). First reverse as elements
- * are always prepended when inserting
- */
cache->priv->lru_start = g_list_reverse (cache->priv->lru_start);
- cache->priv->lru_start = g_list_sort (cache->priv->lru_start, lru_compare_func);
/* frees */
- g_variant_iter_free (entries_iter);
g_variant_unref (cache_variant);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]