Refactor http class to prevent memory leak
authorMichael Rasmussen <mir@datanom.net>
Sun, 27 Jan 2019 11:21:37 +0000 (12:21 +0100)
committerAndrej Kacian <ticho@claws-mail.org>
Tue, 12 Feb 2019 18:38:10 +0000 (19:38 +0100)
Signed-off-by: Michael Rasmussen <mir@datanom.net>
src/plugins/litehtml_viewer/http.cpp
src/plugins/litehtml_viewer/http.h
src/plugins/litehtml_viewer/lh_widget.cpp

index 7472bd7aba47c50b5675c3f90543c56b6424795d..bed56383c72bf216ba383f45d6014041b7ed4f7d 100644 (file)
@@ -22,11 +22,13 @@ http::http()
     curl_easy_setopt(curl, CURLOPT_TCP_KEEPIDLE, 120L);
     curl_easy_setopt(curl, CURLOPT_TCP_KEEPINTVL, 60L);
     curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, http::curl_write_data);
+    stream = NULL;
 }
 
 http::~http()
 {
     curl_easy_cleanup(curl);
+    destroy_giostream();
 }
 
 size_t http::curl_write_data(char* ptr, size_t size, size_t nmemb, void* data_ptr) {
@@ -48,12 +50,12 @@ size_t http::curl_write_data(char* ptr, size_t size, size_t nmemb, void* data_pt
     return realsize;
 }
 
-void http::destroy_giostream(gpointer data) {
-    GInputStream* gio;
-    if (data) {
-       gio = G_INPUT_STREAM(data);
-       g_input_stream_close(gio, NULL, NULL);
-       gio = NULL;
+void http::destroy_giostream() {
+    debug_print("destroy_giostream called.\n");
+    if (stream) {
+       debug_print("Freeing input_stream\n");
+       g_input_stream_close(stream, NULL, NULL);
+       g_object_unref(stream);
     }
 }
 
@@ -63,7 +65,6 @@ GInputStream *http::load_url(const gchar *url, GError **error)
     CURLcode res = CURLE_OK;
     gsize len;
     gchar* content;
-    GInputStream* stream = NULL;
     struct Data data;
 
     data.memory = (char *) g_malloc(1);
@@ -72,7 +73,7 @@ GInputStream *http::load_url(const gchar *url, GError **error)
     if (!strncmp(url, "file:///", 8) || g_file_test(url, G_FILE_TEST_EXISTS)) {
        gchar* newurl = g_filename_from_uri(url, NULL, NULL);
        if (g_file_get_contents(newurl ? newurl : url, &content, &len, &_error)) {
-           stream = g_memory_input_stream_new_from_data(content, len, http::destroy_giostream);
+           stream = g_memory_input_stream_new_from_data(content, len, NULL);
        } else {
            debug_print("Got error: %s\n", _error->message);
        }
@@ -86,7 +87,8 @@ GInputStream *http::load_url(const gchar *url, GError **error)
            _error = g_error_new_literal(G_FILE_ERROR, res, curl_easy_strerror(res));
        } else {
            debug_print("Image size: %d\n", data.size);
-           stream = g_memory_input_stream_new_from_data(g_memdup(data.memory, data.size), data.size, http::destroy_giostream);
+           stream = g_memory_input_stream_new_from_data(
+               g_memdup(data.memory, data.size), data.size, NULL);
            g_free(data.memory);
        }
     }
index c8c3bee6492aeb2189a63f18a797da9401561639..d0ae4c84cf6724a4a410c46286b29b2c47191141 100644 (file)
@@ -11,6 +11,7 @@
 class http
 {
     CURL*           curl;
+    GInputStream*   stream;
 
 public:
     http();
@@ -20,7 +21,7 @@ public:
 
 private:
     static size_t curl_write_data(char* ptr, size_t size, size_t nmemb, void* data_ptr);
-    static void destroy_giostream(gpointer data);
+    void destroy_giostream();
 };
 
 
index c561e9c29c0571cc122a1a66d2e4627cfe86c92b..8db070cf356c61dc927457ef108098890d9caca3 100644 (file)
@@ -92,7 +92,6 @@ lh_widget::lh_widget()
                                GDK_BUTTON_RELEASE_MASK
                              | GDK_BUTTON_PRESS_MASK
                              | GDK_POINTER_MOTION_MASK);
-
 }
 
 lh_widget::~lh_widget()
@@ -153,6 +152,7 @@ GdkPixbuf *lh_widget::get_image(const litehtml::tchar_t* url, bool redraw_on_rea
 {
        GError *error = NULL;
        GdkPixbuf *pixbuf = NULL;
+       http* http_loader = NULL;
 
        if (!lh_prefs_get()->enable_remote_content) {
                debug_print("blocking download of image from '%s'\n", url);
@@ -164,8 +164,8 @@ GdkPixbuf *lh_widget::get_image(const litehtml::tchar_t* url, bool redraw_on_rea
         lh_widget_statusbar_push(msg);
        g_free(msg);
        
-       http http_loader;
-       GInputStream *image = http_loader.load_url(url, &error);
+       http_loader = new http();
+       GInputStream *image = http_loader->load_url(url, &error);
     
        if (error || !image) {
            if (error) {
@@ -178,11 +178,9 @@ GdkPixbuf *lh_widget::get_image(const litehtml::tchar_t* url, bool redraw_on_rea
        pixbuf = gdk_pixbuf_new_from_stream(image, NULL, &error);
        if (error) {
            g_warning("lh_widget::get_image: Could not create pixbuf %s", error->message);
-           //g_object_unref(pixbuf);
            pixbuf = NULL;
            g_clear_error(&error);
        }
-       g_input_stream_close(image, NULL, NULL);
 
 /*     if (redraw_on_ready) {
                redraw();
@@ -190,6 +188,9 @@ GdkPixbuf *lh_widget::get_image(const litehtml::tchar_t* url, bool redraw_on_rea
 
 statusbar_pop:
        lh_widget_statusbar_pop();
+       if (http_loader) {
+               delete http_loader;
+       }
        
        return pixbuf;
 }