From e43916d7d1409e4031d56ee1704456bef55eeb1d Mon Sep 17 00:00:00 2001
From: Daniel Friesel <derf@finalrewind.org>
Date: Fri, 28 Aug 2020 23:09:38 +0200
Subject: Fix segfault when closing a window in multi-window reload mode

Issue:

* start feh --multiwindow --reload 5
* close a window with "x"
* wait up to 5 seconds
* segfault

The issue was caused by the closed window's reload timer still being active
even after the winwidget was free'd.
---
 src/timers.c    | 33 ++++++++++++++++++++++++++++++++-
 src/timers.h    |  2 +-
 src/winwidget.c |  4 ++++
 3 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/src/timers.c b/src/timers.c
index 4bdd64e..b2cdbc7 100644
--- a/src/timers.c
+++ b/src/timers.c
@@ -58,7 +58,37 @@ double feh_get_time(void)
 	return((double) timev.tv_sec + (((double) timev.tv_usec) / 1000000));
 }
 
-void feh_remove_timer(char *name)
+void feh_remove_timer_by_data(void *data)
+{
+	fehtimer ft, ptr, pptr;
+
+	D(("removing timer for %p\n", data));
+	pptr = NULL;
+	ptr = first_timer;
+	while (ptr) {
+		D(("Stepping through event list\n"));
+		ft = ptr;
+		if (ft->data == data) {
+			D(("Found it. Removing\n"));
+			if (pptr)
+				pptr->next = ft->next;
+			else
+				first_timer = ft->next;
+			if (ft->next)
+				ft->next->in += ft->in;
+			if (ft->name)
+				free(ft->name);
+			if (ft)
+				free(ft);
+			return;
+		}
+		pptr = ptr;
+		ptr = ptr->next;
+	}
+	return;
+}
+
+static void feh_remove_timer(char *name)
 {
 	fehtimer ft, ptr, pptr;
 
@@ -88,6 +118,7 @@ void feh_remove_timer(char *name)
 	return;
 }
 
+
 void feh_add_timer(void (*func) (void *data), void *data, double in, char *name)
 {
 	fehtimer ft, ptr, pptr;
diff --git a/src/timers.h b/src/timers.h
index a4243ca..e95d9b5 100644
--- a/src/timers.h
+++ b/src/timers.h
@@ -37,7 +37,7 @@ struct __fehtimer {
 
 void feh_handle_timer(void);
 double feh_get_time(void);
-void feh_remove_timer(char *name);
+void feh_remove_timer_by_data(void *data);
 void feh_add_timer(void (*func) (void *data), void *data, double in, char *name);
 void feh_add_unique_timer(void (*func) (void *data), void *data, double in);
 
diff --git a/src/winwidget.c b/src/winwidget.c
index 6ff90ed..bfd987d 100644
--- a/src/winwidget.c
+++ b/src/winwidget.c
@@ -29,6 +29,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "winwidget.h"
 #include "options.h"
 #include "events.h"
+#include "timers.h"
 
 #ifdef HAVE_INOTIFY
 #include <sys/inotify.h>
@@ -673,6 +674,9 @@ void winwidget_destroy(winwidget winwid)
 #ifdef HAVE_INOTIFY
     winwidget_inotify_remove(winwid);
 #endif
+	if (opt.reload > 0 && opt.multiwindow) {
+		feh_remove_timer_by_data(winwid);
+	}
 	winwidget_destroy_xwin(winwid);
 	if (winwid->name)
 		free(winwid->name);
-- 
cgit v1.2.3