neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit 95f5cf96912727a1ede055211645ac9779f3da44
parent 3173d07564e7cdf0834099a379f0faf480c76224
Author: zeertzjq <zeertzjq@outlook.com>
Date:   Tue, 29 Nov 2022 19:02:29 +0800

vim-patch:9.0.0967: leaking memory from autocmd windows

Problem:    Leaking memory from autocmd windows.
Solution:   Free window when auc_win is not NULL.

https://github.com/vim/vim/commit/84497cd06f06516f6ce727ea00c47792ce16dc70

Co-authored-by: Bram Moolenaar <Bram@vim.org>

Diffstat:
Msrc/nvim/autocmd.c | 15+++++++--------
Msrc/nvim/eval.c | 3++-
Msrc/nvim/globals.h | 5+++--
Msrc/nvim/window.c | 10+++++-----
4 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c @@ -665,12 +665,7 @@ void free_all_autocmds(void) }) map_destroy(int, String)(&map_augroup_id_to_name); - 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 @@ -1418,10 +1413,12 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf) if (win == NULL) { for (auc_idx = 0; auc_idx < AUCMD_WIN_COUNT; auc_idx++) { if (!aucmd_win[auc_idx].auc_win_used) { - win_alloc_aucmd_win(auc_idx); + if (aucmd_win[auc_idx].auc_win == NULL) { + win_alloc_aucmd_win(auc_idx); + need_append = false; + } auc_win = aucmd_win[auc_idx].auc_win; aucmd_win[auc_idx].auc_win_used = true; - need_append = false; break; } } @@ -1520,6 +1517,8 @@ win_found: grid_free(&curwin->w_grid_alloc); } + // 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; if (!valid_tabpage_win(curtab)) { diff --git a/src/nvim/eval.c b/src/nvim/eval.c @@ -4174,8 +4174,9 @@ bool garbage_collect(bool testing) ABORTING(set_ref_in_fmark)(wp->w_jumplist[i].fmark, copyID); } } + // 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) { ABORTING(set_ref_in_item)(&aucmd_win[i].auc_win->w_winvar.di_tv, copyID, NULL, NULL); } } diff --git a/src/nvim/globals.h b/src/nvim/globals.h @@ -429,8 +429,9 @@ EXTERN win_T *curwin; // currently active window enum { 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. + bool auc_win_used; ///< This auc_win is being used. } aucmdwin_T; EXTERN aucmdwin_T aucmd_win[AUCMD_WIN_COUNT]; diff --git a/src/nvim/window.c b/src/nvim/window.c @@ -3092,18 +3092,18 @@ void win_free_all(void) win_remove(lastwin, NULL); int dummy; (void)win_free_mem(wp, &dummy, NULL); - for (int i = 0; i < AUCMD_WIN_COUNT; ++i) { + for (int i = 0; i < AUCMD_WIN_COUNT; i++) { if (aucmd_win[i].auc_win == wp) { - aucmd_win[i].auc_win_used = false; + aucmd_win[i].auc_win = NULL; } } } - for (int i = 0; i < AUCMD_WIN_COUNT; ++i) { - if (aucmd_win[i].auc_win_used) { + for (int i = 0; i < AUCMD_WIN_COUNT; i++) { + if (aucmd_win[i].auc_win != NULL) { int dummy; (void)win_free_mem(aucmd_win[i].auc_win, &dummy, NULL); - aucmd_win[i].auc_win_used = false; + aucmd_win[i].auc_win = NULL; } }