diff options
author | Bram Moolenaar <Bram@vim.org> | 2018-10-14 21:41:01 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2018-10-14 21:41:01 +0200 |
commit | 27e80c885bcb5c5cf6a6462d71d6c81b06ba2451 (patch) | |
tree | 5f23ab7eeb2ddc833a739d7c0ac62c0dd3a2e863 /src/userfunc.c | |
parent | a16bc5450359294f9d8585da9f74e5082108b7fb (diff) | |
download | vim-git-27e80c885bcb5c5cf6a6462d71d6c81b06ba2451.tar.gz |
patch 8.1.0475: memory not freed on exit when quit in autocmdv8.1.0475
Problem: Memory not freed on exit when quit in autocmd.
Solution: Remember funccal stack when executing autocmd.
Diffstat (limited to 'src/userfunc.c')
-rw-r--r-- | src/userfunc.c | 71 |
1 files changed, 30 insertions, 41 deletions
diff --git a/src/userfunc.c b/src/userfunc.c index f6e16fefd..ec239c771 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -1175,6 +1175,33 @@ func_name_refcount(char_u *name) return isdigit(*name) || *name == '<'; } +static funccal_entry_T *funccal_stack = NULL; + +/* + * Save the current function call pointer, and set it to NULL. + * Used when executing autocommands and for ":source". + */ + void +save_funccal(funccal_entry_T *entry) +{ + entry->top_funccal = current_funccal; + entry->next = funccal_stack; + funccal_stack = entry; + current_funccal = NULL; +} + + void +restore_funccal(void) +{ + if (funccal_stack == NULL) + IEMSG("INTERNAL: restore_funccal()"); + else + { + current_funccal = funccal_stack->top_funccal; + funccal_stack = funccal_stack->next; + } +} + #if defined(EXITFREE) || defined(PROTO) void free_all_functions(void) @@ -1185,11 +1212,13 @@ free_all_functions(void) long_u todo = 1; long_u used; - /* Clean up the call stack. */ + /* Clean up the current_funccal chain and the funccal stack. */ while (current_funccal != NULL) { clear_tv(current_funccal->rettv); cleanup_function_call(current_funccal); + if (current_funccal == NULL && funccal_stack != NULL) + restore_funccal(); } /* First clear what the functions contain. Since this may lower the @@ -3578,27 +3607,6 @@ current_func_returned(void) return current_funccal->returned; } -/* - * Save the current function call pointer, and set it to NULL. - * Used when executing autocommands and for ":source". - */ - void * -save_funccal(void) -{ - funccall_T *fc = current_funccal; - - current_funccal = NULL; - return (void *)fc; -} - - void -restore_funccal(void *vfc) -{ - funccall_T *fc = (funccall_T *)vfc; - - current_funccal = fc; -} - int free_unref_funccal(int copyID, int testing) { @@ -3702,25 +3710,6 @@ get_funccal_args_var() } /* - * Clear the current_funccal and return the old value. - * Caller is expected to invoke restore_current_funccal(). - */ - void * -clear_current_funccal() -{ - funccall_T *f = current_funccal; - - current_funccal = NULL; - return f; -} - - void -restore_current_funccal(void *f) -{ - current_funccal = f; -} - -/* * List function variables, if there is a function. */ void |