PATCH: curses: free subwindows before parents or they don't get freed at all

Mikael Magnusson <[email protected]>
Newsgroups gmane.comp.shells.zsh.devel
Message-ID <[email protected]>
---
 Src/Modules/curses.c | 35 +++++++++++++++++++++++++----------
 1 file changed, 25 insertions(+), 10 deletions(-)

diff --git a/Src/Modules/curses.c b/Src/Modules/curses.c
index e630388d61..a6d6cecf36 100644
--- a/Src/Modules/curses.c
+++ b/Src/Modules/curses.c
@@ -284,8 +284,14 @@ zcurses_validate_window(char *win, int criteria)
 static int
 zcurses_free_window(ZCWin w)
 {
-    if (!(w->flags & ZCWF_PERMANENT) && delwin(w->win)!=OK)
-	return 1;
+    int ret = 0;
+
+    if (!(w->flags & ZCWF_PERMANENT) && delwin(w->win)!=OK) {
+	DPUTS2(1, "BUG: Failed to delete ncurses window %s with %d children",
+		w->name ? w->name : "(null)",
+		w->children ? countlinknodes(w->children) : 0);
+	ret = 1;
+    }
 
     if (w->name)
 	zsfree(w->name);
@@ -295,7 +301,7 @@ zcurses_free_window(ZCWin w)
 
     zfree(w, sizeof(struct zc_win));
 
-    return 0;
+    return ret;
 }
 
 static struct zcurses_namenumberpair *
@@ -556,7 +562,9 @@ zccmd_addwin(const char *nam, char **args)
 	return 1;
     }
 
-    zinsertlinknode(zcurses_windows, lastnode(zcurses_windows), (void *)w);
+    /* prepend window so that freelinklist will free children before parents,
+     * otherwise they will be leaked */
+    zinsertlinknode(zcurses_windows, (LinkNode)zcurses_windows, (void *)w);
 
     return 0;
 }
@@ -839,6 +847,14 @@ zccmd_endwin(UNUSED(const char *nam), UNUSED(char **args))
 	 * doing stuff with shttyinfo when we shouldn't really be.
 	 */
 	gettyinfo(&shttyinfo);
+	freelinklist(zcurses_windows, (FreeFunc) zcurses_free_window);
+	zcurses_windows = znewlinklist();
+	if (zcurses_colorpairs) {
+	    deletehashtable(zcurses_colorpairs);
+	    zcurses_colorpairs = NULL;
+	}
+	next_cp = 0;
+	zc_color_phase = 0;
     }
     return 0;
 }
@@ -1667,14 +1683,14 @@ static char **
 zcurses_windowsgetfn(UNUSED(Param pm))
 {
     LinkNode node;
-    char **arr, **arrptr;
+    char **arr;
     int count = countlinknodes(zcurses_windows);
 
-    arrptr = arr = (char **)zhalloc((count+1) * sizeof(char *));
+    arr = (char **)zhalloc((count+1) * sizeof(char *)) + count;
+    *arr = NULL;
 
     for (node = firstnode(zcurses_windows); node; incnode(node))
-	*arrptr++ = dupstring(((ZCWin)getdata(node))->name);
-    *arrptr = NULL;
+	*--arr = dupstring(((ZCWin)getdata(node))->name);
 
     return arr;
 }
@@ -1770,9 +1786,8 @@ boot_(UNUSED(Module m))
 int
 cleanup_(Module m)
 {
+    zccmd_endwin(NULL, NULL);
     freelinklist(zcurses_windows, (FreeFunc) zcurses_free_window);
-    if (zcurses_colorpairs)
-	deletehashtable(zcurses_colorpairs);
     return setfeatureenables(m, &module_features, NULL);
 }
 
-- 
2.38.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.