From 09fa61eb737aa93fb2e99d383c46bcf35d5d730d Mon Sep 17 00:00:00 2001 From: Daniel Silverstone Date: Sat, 15 Jun 2019 21:10:15 +0100 Subject: [PATCH] hlcache.c: Clean up LOADING contents during finalise During the process of finalising the hlcache, there won't be any more fetching going on. As such, we can abort, error, and then destroy any contents still in the process of loading. This should reduce our leaks during shutdown. Signed-off-by: Daniel Silverstone --- content/hlcache.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/content/hlcache.c b/content/hlcache.c index 33436f7ed..61cdebe71 100644 --- a/content/hlcache.c +++ b/content/hlcache.c @@ -36,6 +36,8 @@ #include "content/mimesniff.h" #include "content/hlcache.h" +// Note, this is *ONLY* so that we can abort cleanly during shutdown of the cache +#include "content/content_protected.h" typedef struct hlcache_entry hlcache_entry; typedef struct hlcache_retrieval_ctx hlcache_retrieval_ctx; @@ -104,9 +106,10 @@ static struct hlcache_s *hlcache = NULL; /** * Attempt to clean the cache */ -static void hlcache_clean(void *ignored) +static void hlcache_clean(void *force_clean_flag) { hlcache_entry *entry, *next; + bool force_clean = (force_clean_flag != NULL); for (entry = hlcache->content_list; entry != NULL; entry = next) { next = entry->next; @@ -114,12 +117,17 @@ static void hlcache_clean(void *ignored) if (entry->content == NULL) continue; - if (content__get_status(entry->content) == CONTENT_STATUS_LOADING) - continue; - if (content_count_users(entry->content) != 0) continue; + if (content__get_status(entry->content) == CONTENT_STATUS_LOADING) { + if (force_clean == false) + continue; + NSLOG(netsurf, DEBUG, "Forcing content cleanup during shutdown"); + content_abort(entry->content); + content_set_error(entry->content); + } + /** \todo This is over-zealous: all unused contents * will be immediately destroyed. Ideally, we want to * purge all unused contents that are using stale @@ -581,6 +589,20 @@ void hlcache_finalise(void) } } while (num_contents > 0 && num_contents != prev_contents); + NSLOG(netsurf, INFO, "%d contents remaining after being polite", num_contents); + + /* Drain cache again, forcing the matter */ + do { + prev_contents = num_contents; + + hlcache_clean(&entry); // Any non-NULL pointer will do + + for (num_contents = 0, entry = hlcache->content_list; + entry != NULL; entry = entry->next) { + num_contents++; + } + } while (num_contents > 0 && num_contents != prev_contents); + NSLOG(netsurf, INFO, "%d contents remaining:", num_contents); for (entry = hlcache->content_list; entry != NULL; entry = entry->next) { hlcache_handle entry_handle = { entry, NULL, NULL };