changeset 9844:9ce5941b77d3 v7.4.2197

commit https://github.com/vim/vim/commit/c257487035f83aabe1c7e07f0552309e98f1bcb1 Author: Bram Moolenaar <Bram@vim.org> Date: Thu Aug 11 22:51:05 2016 +0200 patch 7.4.2197 Problem: All functions are freed on exit, which may hide leaks. Solution: Only free named functions, not reference counted ones.
author Christian Brabandt <cb@256bit.org>
date Thu, 11 Aug 2016 23:00:07 +0200
parents 3d9bdb665d6a
children bc0c23856bc6
files src/userfunc.c src/version.c
diffstat 2 files changed, 38 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -1099,22 +1099,53 @@ func_free(ufunc_T *fp, int force)
     vim_free(fp);
 }
 
+/*
+ * There are two kinds of function names:
+ * 1. ordinary names, function defined with :function
+ * 2. numbered functions and lambdas
+ * For the first we only count the name stored in func_hashtab as a reference,
+ * using function() does not count as a reference, because the function is
+ * looked up by name.
+ */
+    static int
+func_name_refcount(char_u *name)
+{
+    return isdigit(*name) || *name == '<';
+}
+
 #if defined(EXITFREE) || defined(PROTO)
     void
 free_all_functions(void)
 {
     hashitem_T	*hi;
+    ufunc_T	*fp;
+    long_u	skipped = 0;
+    long_u	todo;
 
     /* Need to start all over every time, because func_free() may change the
      * hash table. */
-    while (func_hashtab.ht_used > 0)
-	for (hi = func_hashtab.ht_array; ; ++hi)
+    while (func_hashtab.ht_used > skipped)
+    {
+	todo = func_hashtab.ht_used;
+	for (hi = func_hashtab.ht_array; todo > 0; ++hi)
 	    if (!HASHITEM_EMPTY(hi))
 	    {
-		func_free(HI2UF(hi), TRUE);
-		break;
+		--todo;
+		/* Only free functions that are not refcounted, those are
+		 * supposed to be freed when no longer referenced. */
+		fp = HI2UF(hi);
+		if (func_name_refcount(fp->uf_name))
+		    ++skipped;
+		else
+		{
+		    func_free(fp, TRUE);
+		    skipped = 0;
+		    break;
+		}
 	    }
-    hash_clear(&func_hashtab);
+    }
+    if (skipped == 0)
+	hash_clear(&func_hashtab);
 }
 #endif
 
@@ -1669,20 +1700,6 @@ theend:
 }
 
 /*
- * There are two kinds of function names:
- * 1. ordinary names, function defined with :function
- * 2. numbered functions and lambdas
- * For the first we only count the name stored in func_hashtab as a reference,
- * using function() does not count as a reference, because the function is
- * looked up by name.
- */
-    static int
-func_name_refcount(char_u *name)
-{
-    return isdigit(*name) || *name == '<';
-}
-
-/*
  * ":function"
  */
     void
--- a/src/version.c
+++ b/src/version.c
@@ -764,6 +764,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2197,
+/**/
     2196,
 /**/
     2195,