summaryrefslogtreecommitdiff
path: root/src/userfunc.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2018-10-14 21:41:01 +0200
committerBram Moolenaar <Bram@vim.org>2018-10-14 21:41:01 +0200
commit27e80c885bcb5c5cf6a6462d71d6c81b06ba2451 (patch)
tree5f23ab7eeb2ddc833a739d7c0ac62c0dd3a2e863 /src/userfunc.c
parenta16bc5450359294f9d8585da9f74e5082108b7fb (diff)
downloadvim-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.c71
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