diff src/userfunc.c @ 14927:162d79d273e6 v8.1.0475

patch 8.1.0475: memory not freed on exit when quit in autocmd commit https://github.com/vim/vim/commit/27e80c885bcb5c5cf6a6462d71d6c81b06ba2451 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Oct 14 21:41:01 2018 +0200 patch 8.1.0475: memory not freed on exit when quit in autocmd Problem: Memory not freed on exit when quit in autocmd. Solution: Remember funccal stack when executing autocmd.
author Bram Moolenaar <Bram@vim.org>
date Sun, 14 Oct 2018 21:45:04 +0200
parents 2c0f454fcdc9
children c5ec5ddbe814
line wrap: on
line diff
--- 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