diff options
author | Daniel Friesel <derf@finalrewind.org> | 2020-12-05 21:28:11 +0100 |
---|---|---|
committer | Daniel Friesel <derf@finalrewind.org> | 2020-12-05 22:00:45 +0100 |
commit | d473ac13e7b70e8ad7a009a0f8c6d793934d03f1 (patch) | |
tree | a18702ab9080abc888ff48a0b2111b98c5e71dc7 | |
parent | 35f60444fe55fa4717ac784931b3cb7455f7a369 (diff) |
free accompanying EXIF data when freeing an image
This fixes two memory bugs that only manifest with exif=1 and long-running
slideshows.
* when feh loads an image, it writes exif data to file->ed. Previously, this
data was never free'd, causing a memory leak on subsequent loads of the same
file.
* As file->ed is never free'd, the accumulated EXIF data consumes a significant
amount of memory over time. with slideshow-delay = 10 and two days of
runtime, feh may exceed 1 GB of memory usage. If the slideshow is so large
that feh does not encounter the same image twice in this time, this is not
detected as a memory leak, as each EXIF data chunk is referenced from the
filelist.
See <https://github.com/derf/feh/issues/553> for details.
Closes #553
-rw-r--r-- | src/imlib.c | 7 | ||||
-rw-r--r-- | src/slideshow.c | 12 | ||||
-rw-r--r-- | src/winwidget.c | 3 |
3 files changed, 21 insertions, 1 deletions
diff --git a/src/imlib.c b/src/imlib.c index 4e8e790..ae9c1be 100644 --- a/src/imlib.c +++ b/src/imlib.c @@ -366,6 +366,13 @@ int feh_load_image(Imlib_Image * im, feh_file * file) file->filename = real_filename; #ifdef HAVE_LIBEXIF + /* + * if we're called from within feh_reload_image, file->ed is already + * populated. + */ + if (file->ed) { + exif_data_unref(file->ed); + } file->ed = exif_get_data(tmpname); #endif } diff --git a/src/slideshow.c b/src/slideshow.c index 07a1e94..2eb10da 100644 --- a/src/slideshow.c +++ b/src/slideshow.c @@ -225,6 +225,18 @@ void slideshow_change_image(winwidget winwid, int change, int render) /* The for loop prevents us looping infinitely */ for (i = 0; i < our_filelist_len; i++) { winwidget_free_image(winwid); +#ifdef HAVE_LIBEXIF + /* + * An EXIF data chunk requires up to 50 kB of space. For large and + * long-running slideshows, this would acculumate gigabytes of + * EXIF data after a few days. We therefore do not cache EXIF data + * in slideshows. + */ + if (FEH_FILE(winwid->file->data)->ed) { + exif_data_unref(FEH_FILE(winwid->file->data)->ed); + FEH_FILE(winwid->file->data)->ed = NULL; + } +#endif switch (change) { case SLIDE_NEXT: current_file = feh_list_jump(filelist, current_file, FORWARD, 1); diff --git a/src/winwidget.c b/src/winwidget.c index bfd987d..119c3af 100644 --- a/src/winwidget.c +++ b/src/winwidget.c @@ -1014,8 +1014,9 @@ void winwidget_rename(winwidget winwid, char *newname) void winwidget_free_image(winwidget w) { - if (w->im) + if (w->im) { gib_imlib_free_image(w->im); + } w->im = NULL; w->im_w = 0; w->im_h = 0; |