summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2022-11-28 20:34:52 +0000
committerBram Moolenaar <Bram@vim.org>2022-11-28 20:34:52 +0000
commit84497cd06f06516f6ce727ea00c47792ce16dc70 (patch)
tree5cba204eafbd2506cc306d610f646f23d65a2d9b
parentf86490ed4fdab213a28f667abd055c023a73d645 (diff)
patch 9.0.0967: leaking memory from autocmd windowsv9.0.0967
Problem: Leaking memory from autocmd windows. Solution: Free window when auc_win is not NULL.
-rw-r--r--src/autocmd.c17
-rw-r--r--src/eval.c3
-rw-r--r--src/globals.h5
-rw-r--r--src/quickfix.c6
-rw-r--r--src/screen.c4
-rw-r--r--src/version.c2
-rw-r--r--src/window.c4
7 files changed, 21 insertions, 20 deletions
diff --git a/src/autocmd.c b/src/autocmd.c
index 3a08128133..aca990cb51 100644
--- a/src/autocmd.c
+++ b/src/autocmd.c
@@ -653,12 +653,7 @@ free_all_autocmds(void)
}
ga_clear(&augroups);
- for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
- if (aucmd_win[i].auc_win_used)
- {
- aucmd_win[i].auc_win_used = FALSE;
- win_remove(aucmd_win[i].auc_win, NULL);
- }
+ // aucmd_win[] is freed in win_free_all()
}
#endif
@@ -1553,12 +1548,11 @@ aucmd_prepbuf(
for (auc_idx = 0; auc_idx < AUCMD_WIN_COUNT; ++auc_idx)
if (!aucmd_win[auc_idx].auc_win_used)
{
- auc_win = win_alloc_popup_win();
+ if (aucmd_win[auc_idx].auc_win == NULL)
+ aucmd_win[auc_idx].auc_win = win_alloc_popup_win();
+ auc_win = aucmd_win[auc_idx].auc_win;
if (auc_win != NULL)
- {
- aucmd_win[auc_idx].auc_win = auc_win;
aucmd_win[auc_idx].auc_win_used = TRUE;
- }
break;
}
@@ -1667,6 +1661,9 @@ win_found:
// Remove the window and frame from the tree of frames.
(void)winframe_remove(curwin, &dummy, NULL);
win_remove(curwin, NULL);
+
+ // The window is marked as not used, but it is not freed, it can be
+ // used again.
aucmd_win[aco->use_aucmd_win_idx].auc_win_used = FALSE;
last_status(FALSE); // may need to remove last status line
diff --git a/src/eval.c b/src/eval.c
index c43158a29a..20883d4309 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -5084,8 +5084,9 @@ garbage_collect(int testing)
FOR_ALL_TAB_WINDOWS(tp, wp)
abort = abort || set_ref_in_item(&wp->w_winvar.di_tv, copyID,
NULL, NULL);
+ // window-local variables in autocmd windows
for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
- if (aucmd_win[i].auc_win_used)
+ if (aucmd_win[i].auc_win != NULL)
abort = abort || set_ref_in_item(
&aucmd_win[i].auc_win->w_winvar.di_tv, copyID, NULL, NULL);
#ifdef FEAT_PROP_POPUP
diff --git a/src/globals.h b/src/globals.h
index eadff43c99..e69856801e 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -984,8 +984,9 @@ EXTERN win_T *curwin; // currently active window
#define AUCMD_WIN_COUNT 5
typedef struct {
- win_T *auc_win; // window used in aucmd_prepbuf()
- int auc_win_used; // this auc_win is being used
+ win_T *auc_win; // Window used in aucmd_prepbuf(). When not NULL the
+ // window has been allocated.
+ int auc_win_used; // This auc_win is being used.
} aucmdwin_T;
EXTERN aucmdwin_T aucmd_win[AUCMD_WIN_COUNT];
diff --git a/src/quickfix.c b/src/quickfix.c
index e8716d2680..4c414e0ad9 100644
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -6639,10 +6639,10 @@ load_dummy_buffer(
// restore curwin/curbuf and a few other things
aucmd_restbuf(&aco);
- }
- if (newbuf_to_wipe.br_buf != NULL && bufref_valid(&newbuf_to_wipe))
- wipe_buffer(newbuf_to_wipe.br_buf, FALSE);
+ if (newbuf_to_wipe.br_buf != NULL && bufref_valid(&newbuf_to_wipe))
+ wipe_buffer(newbuf_to_wipe.br_buf, FALSE);
+ }
// Add back the "dummy" flag, otherwise buflist_findname_stat() won't
// skip it.
diff --git a/src/screen.c b/src/screen.c
index 3bf15d6c85..c5c6a7ac97 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -2439,7 +2439,7 @@ retry:
FOR_ALL_TAB_WINDOWS(tp, wp)
win_free_lsize(wp);
for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
- if (aucmd_win[i].auc_win_used)
+ if (aucmd_win[i].auc_win != NULL)
win_free_lsize(aucmd_win[i].auc_win);
#ifdef FEAT_PROP_POPUP
// global popup windows
@@ -2484,7 +2484,7 @@ retry:
}
}
for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
- if (aucmd_win[i].auc_win_used
+ if (aucmd_win[i].auc_win != NULL
&& aucmd_win[i].auc_win->w_lines == NULL
&& win_alloc_lines(aucmd_win[i].auc_win) == FAIL)
{
diff --git a/src/version.c b/src/version.c
index 240def4532..395bb2ad73 100644
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 967,
+/**/
966,
/**/
965,
diff --git a/src/window.c b/src/window.c
index 24f25d65b7..9a49cad8d1 100644
--- a/src/window.c
+++ b/src/window.c
@@ -3293,10 +3293,10 @@ win_free_all(void)
tabpage_close(TRUE);
for (int i = 0; i < AUCMD_WIN_COUNT; ++i)
- if (aucmd_win[i].auc_win_used)
+ if (aucmd_win[i].auc_win != NULL)
{
(void)win_free_mem(aucmd_win[i].auc_win, &dummy, NULL);
- aucmd_win[i].auc_win_used = FALSE;
+ aucmd_win[i].auc_win = NULL;
}
while (firstwin != NULL)