Commit d473ac13 authored by Birte Kristina Friesel's avatar Birte Kristina Friesel
Browse files

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
parent 35f60444
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -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
		}
+12 −0
Original line number Diff line number Diff line
@@ -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);
+2 −1
Original line number Diff line number Diff line
@@ -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;