From c206e5e68a1e009df93cf9175d521a4c587158d1 Mon Sep 17 00:00:00 2001 From: Jorge Arellano Cid Date: Fri, 8 May 2009 16:39:19 -0400 Subject: Fix a memory leak when stopping an image-decoding process --- src/dgif.h | 2 +- src/dicache.c | 17 ++++++++++++----- src/dicache.h | 1 - src/djpeg.h | 2 +- src/gif.c | 45 +++++++++++++++++++++++++++++---------------- src/jpeg.c | 27 +++++++++++++++++++++------ src/png.c | 33 +++++++++++++++++++++++---------- 7 files changed, 87 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/dgif.h b/src/dgif.h index d4980e54..ec36812d 100644 --- a/src/dgif.h +++ b/src/dgif.h @@ -10,7 +10,7 @@ extern "C" { void *a_Gif_new(DilloImage *Image, DilloUrl *url, int version); -void a_Gif_callback(int Op, CacheClient_t *Client); +void a_Gif_callback(int Op, void *data); #ifdef __cplusplus diff --git a/src/dicache.c b/src/dicache.c index 6ffa6559..2e5a442b 100644 --- a/src/dicache.c +++ b/src/dicache.c @@ -175,7 +175,7 @@ static void Dicache_remove(const DilloUrl *Url, int version) { DICacheNode *node; DICacheEntry *entry, *prev; - + _MSG("Dicache_remove url=%s\n", URL_STR(Url)); node = dList_find_sorted(CachedIMGs, Url, Dicache_node_by_url_cmp); prev = entry = (node) ? node->first : NULL; @@ -185,10 +185,15 @@ static void Dicache_remove(const DilloUrl *Url, int version) } if (entry) { + _MSG("Dicache_remove Decoder=%p DecoderData=%p\n", + entry->Decoder, entry->DecoderData); /* Eliminate this dicache entry */ dFree(entry->cmap); a_Bitvec_free(entry->BitVec); a_Imgbuf_unref(entry->v_imgbuf); + if (entry->Decoder) { + entry->Decoder(CA_Abort, entry->DecoderData); + } dicache_size_total -= entry->TotalSize; if (node->first == entry) { @@ -208,12 +213,13 @@ static void Dicache_remove(const DilloUrl *Url, int version) /* * Unrefs the counter of a dicache entry, and _if_ no DwImage is acessing - * this buffer, then we call Dicache_free to do the dirty job. + * this buffer, then we call Dicache_remove() to do the job. */ void a_Dicache_unref(const DilloUrl *Url, int version) { DICacheEntry *entry; + _MSG("a_Dicache_unref\n"); if ((entry = a_Dicache_get_entry(Url, version))) { if (--entry->RefCount == 0) { Dicache_remove(Url, version); @@ -419,9 +425,10 @@ static void *Dicache_image(int ImgType, const char *MimeType, void *Ptr, /* Repeated image */ a_Dicache_ref(DicEntry->url, DicEntry->version); } - DicEntry->Decoder = (ImgType == DIC_Png) ? a_Png_callback : - (ImgType == DIC_Gif) ? a_Gif_callback : - (ImgType == DIC_Jpeg) ? a_Jpeg_callback : NULL; + DicEntry->Decoder = (ImgType == DIC_Png) ? (CA_Callback_t)a_Png_callback : + (ImgType == DIC_Gif) ? (CA_Callback_t)a_Gif_callback : + (ImgType == DIC_Jpeg) ? (CA_Callback_t)a_Jpeg_callback: + NULL; *Data = DicEntry->DecoderData; *Call = (CA_Callback_t) a_Dicache_callback; diff --git a/src/dicache.h b/src/dicache.h index b4ef714d..b7bbb61c 100644 --- a/src/dicache.h +++ b/src/dicache.h @@ -60,7 +60,6 @@ void *a_Dicache_gif_image(const char *Type, void *Ptr, CA_Callback_t *Call, void *a_Dicache_jpeg_image(const char *Type, void *Ptr, CA_Callback_t *Call, void **Data); void a_Dicache_callback(int Op, CacheClient_t *Client); -void a_Dicache_callback2(int Op, CacheClient_t *Client); void a_Dicache_set_parms(DilloUrl *url, int version, DilloImage *Image, uint_t width, uint_t height, DilloImgType type); diff --git a/src/djpeg.h b/src/djpeg.h index d88f5671..32419e4b 100644 --- a/src/djpeg.h +++ b/src/djpeg.h @@ -10,7 +10,7 @@ extern "C" { void *a_Jpeg_new(DilloImage *Image, DilloUrl *url, int version); -void a_Jpeg_callback(int Op, CacheClient_t *Client); +void a_Jpeg_callback(int Op, void *data); #ifdef __cplusplus diff --git a/src/gif.c b/src/gif.c index 2301b648..85e57584 100644 --- a/src/gif.c +++ b/src/gif.c @@ -153,6 +153,7 @@ static size_t Gif_process_bytes(DilloGif *gif, const uchar_t *buf, void *a_Gif_new(DilloImage *Image, DilloUrl *url, int version) { DilloGif *gif = dMalloc(sizeof(DilloGif)); + MSG("Gif_new: gif=%p\n", gif); gif->Image = Image; gif->url = url; @@ -173,16 +174,39 @@ void *a_Gif_new(DilloImage *Image, DilloUrl *url, int version) return gif; } +/* + * Free the gif-decoding data structure. + */ +static void Gif_free(DilloGif *gif) +{ + int i; + + MSG("Gif_free: gif %p\n", gif); + + dFree(gif->linebuf); + if (gif->spill_lines != NULL) { + for (i = 0; i < gif->num_spill_lines_max; i++) + dFree(gif->spill_lines[i]); + dFree(gif->spill_lines); + } + dFree(gif); +} + /* * This function is a cache client, it receives data from the cache * and dispatches it to the appropriate gif-processing functions */ -void a_Gif_callback(int Op, CacheClient_t *Client) +void a_Gif_callback(int Op, void *data) { - if (Op) - Gif_close(Client->CbData, Client); - else + if (Op == CA_Send) { + CacheClient_t *Client = data; Gif_write(Client->CbData, Client->Buf, Client->BufSize); + } else if (Op == CA_Close) { + CacheClient_t *Client = data; + Gif_close(Client->CbData, Client); + } else if (Op == CA_Abort) { + Gif_free(data); + } } /* @@ -217,20 +241,9 @@ static void Gif_write(DilloGif *gif, void *Buf, uint_t BufSize) */ static void Gif_close(DilloGif *gif, CacheClient_t *Client) { - int i; - _MSG("Gif_close: destroy gif %p\n", gif); - a_Dicache_close(gif->url, gif->version, Client); - - dFree(gif->linebuf); - - if (gif->spill_lines != NULL) { - for (i = 0; i < gif->num_spill_lines_max; i++) - dFree(gif->spill_lines[i]); - dFree(gif->spill_lines); - } - dFree(gif); + Gif_free(gif); } diff --git a/src/jpeg.c b/src/jpeg.c index 9d611ba8..c8a1accf 100644 --- a/src/jpeg.c +++ b/src/jpeg.c @@ -93,6 +93,16 @@ METHODDEF(void) Jpeg_errorexit (j_common_ptr cinfo) longjmp(myerr->setjmp_buffer, 1); } +/* + * Free the jpeg-decoding data structure. + */ +static void Jpeg_free(DilloJpeg *jpeg) +{ + MSG("Jpeg_free %p\n", jpeg); + jpeg_destroy_decompress(&(jpeg->cinfo)); + dFree(jpeg); +} + /* * Finish the decoding process */ @@ -100,8 +110,7 @@ static void Jpeg_close(DilloJpeg *jpeg, CacheClient_t *Client) { _MSG("Jpeg_close\n"); a_Dicache_close(jpeg->url, jpeg->version, Client); - jpeg_destroy_decompress(&(jpeg->cinfo)); - dFree(jpeg); + Jpeg_free(jpeg); } /* @@ -174,6 +183,7 @@ void *a_Jpeg_new(DilloImage *Image, DilloUrl *url, int version) { my_source_mgr *src; DilloJpeg *jpeg = dMalloc(sizeof(*jpeg)); + MSG("Jpeg_new: jpeg=%p\n", jpeg); jpeg->Image = Image; jpeg->url = url; @@ -206,12 +216,17 @@ void *a_Jpeg_new(DilloImage *Image, DilloUrl *url, int version) return jpeg; } -void a_Jpeg_callback(int Op, CacheClient_t *Client) +void a_Jpeg_callback(int Op, void *data) { - if (Op) - Jpeg_close(Client->CbData, Client); - else + if (Op == CA_Send) { + CacheClient_t *Client = data; Jpeg_write(Client->CbData, Client->Buf, Client->BufSize); + } else if (Op == CA_Close) { + CacheClient_t *Client = data; + Jpeg_close(Client->CbData, Client); + } else if (Op == CA_Abort) { + Jpeg_free(data); + } } /* diff --git a/src/png.c b/src/png.c index b6900db1..fac64b8d 100644 --- a/src/png.c +++ b/src/png.c @@ -291,15 +291,12 @@ static void Png_dataend_callback(png_structp png_ptr, png_infop info_ptr) } /* - * Finish the decoding process (and free the memory) + * Free up the resources for this image. */ -static void Png_close(DilloPng *png, CacheClient_t *Client) +static void Png_free(DilloPng *png) { - _MSG("Png_close\n"); - /* Let dicache know decoding is over */ - a_Dicache_close(png->url, png->version, Client); + MSG("Png_free %p\n", png); - /* Free up the resources for this image */ dFree(png->image_data); dFree(png->row_pointers); dFree(png->linebuf); @@ -310,6 +307,17 @@ static void Png_close(DilloPng *png, CacheClient_t *Client) dFree(png); } +/* + * Finish the decoding process (and free the memory) + */ +static void Png_close(DilloPng *png, CacheClient_t *Client) +{ + _MSG("Png_close\n"); + /* Let dicache know decoding is over */ + a_Dicache_close(png->url, png->version, Client); + Png_free(png); +} + /* * Receive and process new chunks of PNG image data */ @@ -402,12 +410,16 @@ static void Png_write(DilloPng *png, void *Buf, uint_t BufSize) * failure. This means that you can't just wait for all the data to be * presented before starting conversion and display. */ -void a_Png_callback(int Op, CacheClient_t *Client) +void a_Png_callback(int Op, void *data) { - if (Op) { /* EOF */ - Png_close(Client->CbData, Client); - } else { + if (Op == CA_Send) { + CacheClient_t *Client = data; Png_write(Client->CbData, Client->Buf, Client->BufSize); + } else if (Op == CA_Close) { + CacheClient_t *Client = data; + Png_close(Client->CbData, Client); + } else if (Op == CA_Abort) { + Png_free(data); } } @@ -417,6 +429,7 @@ void a_Png_callback(int Op, CacheClient_t *Client) void *a_Png_new(DilloImage *Image, DilloUrl *url, int version) { DilloPng *png = dNew0(DilloPng, 1); + MSG("Png_new: png=%p\n", png); png->Image = Image; png->url = url; -- cgit v1.2.3